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.archetype.ui.creation;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.nio.file.Files;
29  import java.nio.file.NoSuchFileException;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import org.apache.maven.archetype.common.ArchetypeFilesResolver;
34  import org.apache.maven.archetype.common.Constants;
35  import org.apache.maven.archetype.exception.ArchetypeNotConfigured;
36  import org.apache.maven.archetype.exception.ArchetypeNotDefined;
37  import org.apache.maven.archetype.ui.ArchetypeConfiguration;
38  import org.apache.maven.archetype.ui.ArchetypeDefinition;
39  import org.apache.maven.archetype.ui.ArchetypeFactory;
40  import org.apache.maven.project.MavenProject;
41  import org.codehaus.plexus.components.interactivity.PrompterException;
42  import org.codehaus.plexus.util.StringUtils;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  @Named("default")
47  @Singleton
48  public class DefaultArchetypeCreationConfigurator implements ArchetypeCreationConfigurator {
49      private static final Logger LOGGER = LoggerFactory.getLogger(DefaultArchetypeCreationConfigurator.class);
50  
51      @Inject
52      private ArchetypeCreationQueryer archetypeCreationQueryer;
53  
54      @Inject
55      private ArchetypeFactory archetypeFactory;
56  
57      @Inject
58      private ArchetypeFilesResolver archetypeFilesResolver;
59  
60      @Override
61      public Properties configureArchetypeCreation(
62              MavenProject project,
63              Boolean interactiveMode,
64              Properties commandLineProperties,
65              File propertyFile,
66              List<String> languages)
67              throws IOException, ArchetypeNotDefined, ArchetypeNotConfigured, PrompterException {
68          Properties properties = initialiseArchetypeProperties(commandLineProperties, propertyFile);
69  
70          ArchetypeDefinition archetypeDefinition = archetypeFactory.createArchetypeDefinition(properties);
71  
72          if (!archetypeDefinition.isDefined()) {
73              archetypeDefinition = defineDefaultArchetype(project, properties);
74          }
75  
76          ArchetypeConfiguration archetypeConfiguration =
77                  archetypeFactory.createArchetypeConfiguration(project, archetypeDefinition, properties);
78  
79          String resolvedPackage = archetypeFilesResolver.resolvePackage(project.getBasedir(), languages);
80  
81          if (!archetypeConfiguration.isConfigured()) {
82              archetypeConfiguration =
83                      defineDefaultConfiguration(project, archetypeDefinition, resolvedPackage, properties);
84          }
85  
86          if (interactiveMode.booleanValue()) {
87              LOGGER.debug("Entering interactive mode");
88  
89              boolean confirmed = false;
90              while (!confirmed) {
91                  if (!archetypeDefinition.isDefined()) // <editor-fold text="...">
92                  {
93                      LOGGER.debug("Archetype is yet not defined");
94                      if (!archetypeDefinition.isGroupDefined()) {
95                          LOGGER.debug("Asking for archetype's groupId");
96                          archetypeDefinition.setGroupId(
97                                  archetypeCreationQueryer.getArchetypeGroupId(project.getGroupId()));
98                      }
99                      if (!archetypeDefinition.isArtifactDefined()) {
100                         LOGGER.debug("Asking for archetype's artifactId");
101                         archetypeDefinition.setArtifactId(archetypeCreationQueryer.getArchetypeArtifactId(
102                                 project.getArtifactId() + Constants.ARCHETYPE_SUFFIX));
103                     }
104                     if (!archetypeDefinition.isVersionDefined()) {
105                         LOGGER.debug("Asking for archetype's version");
106                         archetypeDefinition.setVersion(
107                                 archetypeCreationQueryer.getArchetypeVersion(project.getVersion()));
108                     }
109 
110                     archetypeFactory.updateArchetypeConfiguration(archetypeConfiguration, archetypeDefinition);
111                 } // </editor-fold>
112 
113                 if (!archetypeConfiguration.isConfigured()) // <editor-fold text="...">
114                 {
115                     LOGGER.debug("Archetype is not yet configured");
116                     if (!archetypeConfiguration.isConfigured(Constants.GROUP_ID)) {
117                         LOGGER.debug("Asking for project's groupId");
118                         archetypeConfiguration.setProperty(
119                                 Constants.GROUP_ID,
120                                 archetypeCreationQueryer.getGroupId(
121                                         archetypeConfiguration.getDefaultValue(Constants.GROUP_ID)));
122                     }
123                     if (!archetypeConfiguration.isConfigured(Constants.ARTIFACT_ID)) {
124                         LOGGER.debug("Asking for project's artifactId");
125                         archetypeConfiguration.setProperty(
126                                 Constants.ARTIFACT_ID,
127                                 archetypeCreationQueryer.getArtifactId(
128                                         archetypeConfiguration.getDefaultValue(Constants.ARTIFACT_ID)));
129                     }
130                     if (!archetypeConfiguration.isConfigured(Constants.VERSION)) {
131                         LOGGER.debug("Asking for project's version");
132                         archetypeConfiguration.setProperty(
133                                 Constants.VERSION,
134                                 archetypeCreationQueryer.getVersion(
135                                         archetypeConfiguration.getDefaultValue(Constants.VERSION)));
136                     }
137                     if (!archetypeConfiguration.isConfigured(Constants.PACKAGE)) {
138                         LOGGER.debug("Asking for project's package");
139                         archetypeConfiguration.setProperty(
140                                 Constants.PACKAGE,
141                                 archetypeCreationQueryer.getPackage(
142                                         (resolvedPackage == null || resolvedPackage.isEmpty())
143                                                 ? archetypeConfiguration.getDefaultValue(Constants.PACKAGE)
144                                                 : resolvedPackage));
145                     }
146                 } // </editor-fold>
147 
148                 boolean stopAddingProperties = false;
149                 while (!stopAddingProperties) {
150                     LOGGER.debug("Asking for another required property");
151                     stopAddingProperties = !archetypeCreationQueryer.askAddAnotherProperty();
152 
153                     if (!stopAddingProperties) {
154                         LOGGER.debug("Asking for required property key");
155 
156                         String propertyKey = archetypeCreationQueryer.askNewPropertyKey();
157                         LOGGER.debug("Asking for required property value");
158 
159                         String replacementValue = archetypeCreationQueryer.askReplacementValue(
160                                 propertyKey, archetypeConfiguration.getDefaultValue(propertyKey));
161                         archetypeConfiguration.setDefaultProperty(propertyKey, replacementValue);
162                         archetypeConfiguration.setProperty(propertyKey, replacementValue);
163                     }
164                 }
165 
166                 LOGGER.debug("Asking for configuration confirmation");
167                 if (archetypeCreationQueryer.confirmConfiguration(archetypeConfiguration)) {
168                     confirmed = true;
169                 } else {
170                     LOGGER.debug("Reseting archetype's definition and configuration");
171                     archetypeConfiguration.reset();
172                     archetypeDefinition.reset();
173                 }
174             } // end while
175         } else {
176             LOGGER.debug("Entering batch mode");
177             if (!archetypeDefinition.isDefined()) {
178                 throw new ArchetypeNotDefined("The archetype is not defined");
179             } else if (!archetypeConfiguration.isConfigured()) {
180                 throw new ArchetypeNotConfigured("The archetype is not configured", null);
181             }
182         } // end if
183 
184         return archetypeConfiguration.toProperties();
185     }
186 
187     private ArchetypeDefinition defineDefaultArchetype(MavenProject project, Properties properties) {
188         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_GROUP_ID))) {
189             properties.setProperty(Constants.ARCHETYPE_GROUP_ID, project.getGroupId());
190         }
191         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_ARTIFACT_ID))) {
192             properties.setProperty(
193                     Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() + Constants.ARCHETYPE_SUFFIX);
194         }
195         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_VERSION))) {
196             properties.setProperty(Constants.ARCHETYPE_VERSION, project.getVersion());
197         }
198 
199         return archetypeFactory.createArchetypeDefinition(properties);
200     }
201 
202     private ArchetypeConfiguration defineDefaultConfiguration(
203             MavenProject project,
204             ArchetypeDefinition archetypeDefinition,
205             String resolvedPackage,
206             Properties properties) {
207         if (StringUtils.isEmpty(properties.getProperty(Constants.GROUP_ID))) {
208             LOGGER.info("Setting default groupId: " + project.getGroupId());
209             properties.setProperty(Constants.GROUP_ID, project.getGroupId());
210         }
211 
212         if (StringUtils.isEmpty(properties.getProperty(Constants.ARTIFACT_ID))) {
213             LOGGER.info("Setting default artifactId: " + project.getArtifactId());
214             properties.setProperty(Constants.ARTIFACT_ID, project.getArtifactId());
215         }
216 
217         if (StringUtils.isEmpty(properties.getProperty(Constants.VERSION))) {
218             LOGGER.info("Setting default version: " + project.getVersion());
219             properties.setProperty(Constants.VERSION, project.getVersion());
220         }
221 
222         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_GROUP_ID))) {
223             LOGGER.info("Setting default archetype's groupId: " + project.getGroupId());
224             properties.setProperty(Constants.ARCHETYPE_GROUP_ID, project.getGroupId());
225         }
226 
227         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_ARTIFACT_ID))) {
228             LOGGER.info("Setting default archetype's artifactId: " + project.getArtifactId());
229             properties.setProperty(
230                     Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() + Constants.ARCHETYPE_SUFFIX);
231         }
232 
233         if (StringUtils.isEmpty(properties.getProperty(Constants.ARCHETYPE_VERSION))) {
234             LOGGER.info("Setting default archetype's version: " + project.getVersion());
235             properties.setProperty(Constants.ARCHETYPE_VERSION, project.getVersion());
236         }
237 
238         if (StringUtils.isEmpty(
239                 properties.getProperty(Constants.PACKAGE /*, properties.getProperty ( Constants.PACKAGE_NAME ) */))) {
240             if (resolvedPackage == null || resolvedPackage.isEmpty()) {
241                 resolvedPackage = project.getGroupId();
242             }
243             LOGGER.info("Setting default package: " + resolvedPackage);
244             /* properties.setProperty ( Constants.PACKAGE_NAME, resolvedPackage ); */
245             properties.setProperty(Constants.PACKAGE, resolvedPackage);
246         }
247 
248         return archetypeFactory.createArchetypeConfiguration(project, archetypeDefinition, properties);
249     }
250 
251     private void readProperties(Properties properties, File propertyFile) throws IOException {
252         LOGGER.debug("Reading property file " + propertyFile);
253 
254         try (InputStream is = Files.newInputStream(propertyFile.toPath())) {
255             properties.load(is);
256 
257             LOGGER.debug("Read " + properties.size() + " properties");
258         }
259     }
260 
261     private Properties initialiseArchetypeProperties(Properties commandLineProperties, File propertyFile)
262             throws IOException {
263         Properties properties = new Properties();
264 
265         if (propertyFile != null) {
266             try {
267                 readProperties(properties, propertyFile);
268             } catch (NoSuchFileException ex) {
269                 LOGGER.debug(propertyFile.getName() + "  does not exist");
270             }
271         }
272 
273         return properties;
274     }
275 }