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.wrapper;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.nio.file.Files;
26  import java.nio.file.Path;
27  import java.nio.file.Paths;
28  import java.util.Locale;
29  import java.util.Properties;
30  
31  import static org.apache.maven.wrapper.MavenWrapperMain.MVNW_REPOURL;
32  
33  /**
34   * Wrapper executor, running {@link Installer} to get a Maven distribution ready, followed by
35   * {@link BootstrapMainStarter} to launch the Maven bootstrap.
36   *
37   * @author Hans Dockter
38   */
39  public class WrapperExecutor {
40      public static final String DISTRIBUTION_URL_PROPERTY = "distributionUrl";
41  
42      public static final String DISTRIBUTION_BASE_PROPERTY = "distributionBase";
43  
44      public static final String ZIP_STORE_BASE_PROPERTY = "zipStoreBase";
45  
46      public static final String DISTRIBUTION_PATH_PROPERTY = "distributionPath";
47  
48      public static final String ZIP_STORE_PATH_PROPERTY = "zipStorePath";
49  
50      public static final String DISTRIBUTION_SHA_256_SUM = "distributionSha256Sum";
51  
52      public static final String ALWAYS_DOWNLOAD = "alwaysDownload";
53  
54      public static final String ALWAYS_UNPACK = "alwaysUnpack";
55  
56      private final Properties properties;
57  
58      private final Path propertiesFile;
59  
60      private final WrapperConfiguration config = new WrapperConfiguration();
61  
62      public static WrapperExecutor forProjectDirectory(Path projectDir) {
63          return new WrapperExecutor(projectDir.resolve("maven/wrapper/maven-wrapper.properties"), new Properties());
64      }
65  
66      public static WrapperExecutor forWrapperPropertiesFile(Path propertiesFile) {
67          if (Files.notExists(propertiesFile)) {
68              throw new RuntimeException(
69                      String.format(Locale.ROOT, "Wrapper properties file '%s' does not exist.", propertiesFile));
70          }
71          return new WrapperExecutor(propertiesFile, new Properties());
72      }
73  
74      WrapperExecutor(Path propertiesFile, Properties properties) {
75          this.properties = properties;
76          this.propertiesFile = propertiesFile;
77          if (Files.exists(propertiesFile)) {
78              try {
79                  loadProperties(propertiesFile, properties);
80                  config.setDistribution(prepareDistributionUri());
81                  config.setDistributionBase(getProperty(DISTRIBUTION_BASE_PROPERTY, config.getDistributionBase()));
82                  config.setDistributionPath(Paths.get(getProperty(
83                          DISTRIBUTION_PATH_PROPERTY, config.getDistributionPath().toString())));
84                  config.setZipBase(getProperty(ZIP_STORE_BASE_PROPERTY, config.getZipBase()));
85                  config.setZipPath(Paths.get(
86                          getProperty(ZIP_STORE_PATH_PROPERTY, config.getZipPath().toString())));
87                  config.setDistributionSha256Sum(getProperty(DISTRIBUTION_SHA_256_SUM, ""));
88                  config.setAlwaysUnpack(Boolean.parseBoolean(getProperty(ALWAYS_UNPACK, Boolean.FALSE.toString())));
89                  config.setAlwaysDownload(Boolean.parseBoolean(getProperty(ALWAYS_DOWNLOAD, Boolean.FALSE.toString())));
90              } catch (Exception e) {
91                  throw new RuntimeException(
92                          String.format(Locale.ROOT, "Could not load wrapper properties from '%s'.", propertiesFile), e);
93              }
94          }
95      }
96  
97      protected String getEnv(String key) {
98          return System.getenv(key);
99      }
100 
101     private URI prepareDistributionUri() throws URISyntaxException {
102         URI source = readDistroUrl();
103         if (source.getScheme() == null) {
104             // no scheme means someone passed a relative url. In our context only file relative urls make sense.
105             return propertiesFile
106                     .getParent()
107                     .resolve(source.getSchemeSpecificPart())
108                     .toUri();
109         } else {
110             String mvnwRepoUrl = getEnv(MVNW_REPOURL);
111             if (mvnwRepoUrl != null && !mvnwRepoUrl.isEmpty()) {
112                 Logger.info("Detected MVNW_REPOURL environment variable " + mvnwRepoUrl);
113                 if (mvnwRepoUrl.endsWith("/")) {
114                     mvnwRepoUrl = mvnwRepoUrl.substring(0, mvnwRepoUrl.length() - 1);
115                 }
116                 String distributionPath = source.getPath();
117                 int index = distributionPath.indexOf("org/apache/maven");
118                 if (index > 1) {
119                     distributionPath = "/".concat(distributionPath.substring(index));
120                 } else {
121                     Logger.warn("distributionUrl don't contain package name " + source.getPath());
122                 }
123                 return new URI(mvnwRepoUrl + distributionPath);
124             }
125 
126             return source;
127         }
128     }
129 
130     private URI readDistroUrl() throws URISyntaxException {
131         return new URI(getProperty(DISTRIBUTION_URL_PROPERTY));
132     }
133 
134     private static void loadProperties(Path propertiesFile, Properties properties) throws IOException {
135         try (InputStream inStream = Files.newInputStream(propertiesFile)) {
136             properties.load(inStream);
137         }
138     }
139 
140     /**
141      * Returns the Maven distribution which this wrapper will use. Returns null if no wrapper meta-data was found in the
142      * specified project directory.
143      *
144      * @return the Maven distribution which this wrapper will use
145      */
146     public URI getDistribution() {
147         return config.getDistribution();
148     }
149 
150     /**
151      * Returns the configuration for this wrapper.
152      *
153      * @return the configuration for this wrapper
154      */
155     public WrapperConfiguration getConfiguration() {
156         return config;
157     }
158 
159     public void execute(String[] args, Installer install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
160         Path mavenHome = install.createDist(config);
161         bootstrapMainStarter.start(args, mavenHome);
162     }
163 
164     private String getProperty(String propertyName) {
165         return getProperty(propertyName, null);
166     }
167 
168     private String getProperty(String propertyName, String defaultValue) {
169         String value = properties.getProperty(propertyName, defaultValue);
170         if (value == null) {
171             reportMissingProperty(propertyName);
172         }
173         return value;
174     }
175 
176     private void reportMissingProperty(String propertyName) {
177         throw new RuntimeException(String.format(
178                 Locale.ROOT,
179                 "No value with key '%s' specified in wrapper properties file '%s'.",
180                 propertyName,
181                 propertiesFile));
182     }
183 }