Skip to content

Commit 18a56dd

Browse files
committed
Polish CLI init command
Rename a few classes and methods and extract some logic into helper classes. Also change 2 char shortcuts to a single char. Closes gh-1751
1 parent b89e5e0 commit 18a56dd

22 files changed

+811
-862
lines changed

spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/Dependency.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,30 @@
2222
* @author Stephane Nicoll
2323
* @since 1.2.0
2424
*/
25-
class Dependency {
25+
final class Dependency {
2626

27-
private String id;
27+
private final String id;
2828

29-
private String name;
29+
private final String name;
3030

31-
private String description;
31+
private final String description;
3232

33-
public String getId() {
34-
return this.id;
33+
public Dependency(String id, String name, String description) {
34+
this.id = id;
35+
this.name = name;
36+
this.description = description;
3537
}
3638

37-
public void setId(String id) {
38-
this.id = id;
39+
public String getId() {
40+
return this.id;
3941
}
4042

4143
public String getName() {
4244
return this.name;
4345
}
4446

45-
public void setName(String name) {
46-
this.name = name;
47-
}
48-
4947
public String getDescription() {
5048
return this.description;
5149
}
5250

53-
public void setDescription(String description) {
54-
this.description = description;
55-
}
56-
5751
}

spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitCommand.java

Lines changed: 168 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,18 @@
1616

1717
package org.springframework.boot.cli.command.init;
1818

19+
import java.io.IOException;
20+
import java.util.Arrays;
21+
22+
import joptsimple.OptionSet;
23+
import joptsimple.OptionSpec;
24+
1925
import org.apache.http.impl.client.HttpClientBuilder;
2026
import org.springframework.boot.cli.command.Command;
2127
import org.springframework.boot.cli.command.OptionParsingCommand;
28+
import org.springframework.boot.cli.command.options.OptionHandler;
29+
import org.springframework.boot.cli.command.status.ExitStatus;
30+
import org.springframework.boot.cli.util.Log;
2231

2332
/**
2433
* {@link Command} that initializes a project using Spring initializr.
@@ -28,13 +37,168 @@
2837
*/
2938
public class InitCommand extends OptionParsingCommand {
3039

31-
InitCommand(InitCommandOptionHandler handler) {
32-
super("init", "Initialize a new project structure from Spring Initializr",
33-
handler);
40+
public InitCommand(InitOptionHandler handler) {
41+
super("init", "Initialize a new project using Spring "
42+
+ "Initialzr (start.spring.io)", handler);
3443
}
3544

3645
public InitCommand() {
37-
this(new InitCommandOptionHandler(HttpClientBuilder.create().build()));
46+
this(new InitOptionHandler(getInitializrService()));
47+
}
48+
49+
private static InitializrService getInitializrService() {
50+
return new InitializrService(HttpClientBuilder.create().build());
51+
}
52+
53+
private static class InitOptionHandler extends OptionHandler {
54+
55+
private final ServiceCapabilitiesReportGenerator serviceCapabilitiesReport;
56+
57+
private final ProjectGenerator projectGenerator;
58+
59+
private OptionSpec<String> target;
60+
61+
private OptionSpec<Void> listCapabilities;
62+
63+
private OptionSpec<String> bootVersion;
64+
65+
private OptionSpec<String> dependencies;
66+
67+
private OptionSpec<String> javaVersion;
68+
69+
private OptionSpec<String> packaging;
70+
71+
private OptionSpec<String> build;
72+
73+
private OptionSpec<String> format;
74+
75+
private OptionSpec<String> type;
76+
77+
private OptionSpec<Void> extract;
78+
79+
private OptionSpec<Void> force;
80+
81+
private OptionSpec<String> output;
82+
83+
InitOptionHandler(InitializrService initializrService) {
84+
this.serviceCapabilitiesReport = new ServiceCapabilitiesReportGenerator(
85+
initializrService);
86+
this.projectGenerator = new ProjectGenerator(initializrService);
87+
88+
}
89+
90+
@Override
91+
protected void options() {
92+
this.target = option(Arrays.asList("target"), "URL of the service to use")
93+
.withRequiredArg().defaultsTo(
94+
ProjectGenerationRequest.DEFAULT_SERVICE_URL);
95+
this.listCapabilities = option(Arrays.asList("list", "l"),
96+
"List the capabilities of the service. Use it to discover the "
97+
+ "dependencies and the types that are available");
98+
projectGenerationOptions();
99+
otherOptions();
100+
}
101+
102+
private void projectGenerationOptions() {
103+
this.bootVersion = option(Arrays.asList("boot-version", "b"),
104+
"Spring Boot version to use (for example '1.2.0.RELEASE')")
105+
.withRequiredArg();
106+
this.dependencies = option(
107+
Arrays.asList("dependencies", "d"),
108+
"Comma separated list of dependencies to include in the "
109+
+ "generated project").withRequiredArg();
110+
this.javaVersion = option(Arrays.asList("java-version", "j"),
111+
"Java version to use (for example '1.8')").withRequiredArg();
112+
this.packaging = option(Arrays.asList("packaging", "p"),
113+
"Packaging type to use (for example 'jar')").withRequiredArg();
114+
this.build = option("build",
115+
"The build system to use (for example 'maven' or 'gradle')")
116+
.withRequiredArg().defaultsTo("maven");
117+
this.format = option(
118+
"format",
119+
"The format of the generated content (for example 'build' for a build file, "
120+
+ "'project' for a project archive)").withRequiredArg()
121+
.defaultsTo("project");
122+
this.type = option(
123+
Arrays.asList("type", "t"),
124+
"The project type to use. Not normally needed if you use --build "
125+
+ "and/or --format. Check the capabilities of the service "
126+
+ "(--list) for more details").withRequiredArg();
127+
}
128+
129+
private void otherOptions() {
130+
this.extract = option(Arrays.asList("extract", "x"),
131+
"Extract the project archive");
132+
this.force = option(Arrays.asList("force", "f"),
133+
"Force overwrite of existing files");
134+
this.output = option(
135+
Arrays.asList("output", "o"),
136+
"Location of the generated project. Can be an absolute or a "
137+
+ "relative reference and should refer to a directory when "
138+
+ "--extract is used").withRequiredArg();
139+
}
140+
141+
@Override
142+
protected ExitStatus run(OptionSet options) throws Exception {
143+
try {
144+
if (options.has(this.listCapabilities)) {
145+
generateReport(options);
146+
}
147+
else {
148+
generateProject(options);
149+
}
150+
return ExitStatus.OK;
151+
}
152+
catch (ReportableException ex) {
153+
Log.error(ex.getMessage());
154+
return ExitStatus.ERROR;
155+
}
156+
catch (Exception ex) {
157+
Log.error(ex);
158+
return ExitStatus.ERROR;
159+
}
160+
}
161+
162+
private void generateReport(OptionSet options) throws IOException {
163+
Log.info(this.serviceCapabilitiesReport.generate(options.valueOf(this.target)));
164+
}
165+
166+
protected void generateProject(OptionSet options) throws IOException {
167+
ProjectGenerationRequest request = createProjectGenerationRequest(options);
168+
this.projectGenerator.generateProject(request, options.has(this.force),
169+
options.has(this.extract), options.valueOf(this.output));
170+
}
171+
172+
protected ProjectGenerationRequest createProjectGenerationRequest(
173+
OptionSet options) {
174+
ProjectGenerationRequest request = new ProjectGenerationRequest();
175+
request.setServiceUrl(options.valueOf(this.target));
176+
if (options.has(this.bootVersion)) {
177+
request.setBootVersion(options.valueOf(this.bootVersion));
178+
}
179+
if (options.has(this.dependencies)) {
180+
for (String dep : options.valueOf(this.dependencies).split(",")) {
181+
request.getDependencies().add(dep.trim());
182+
}
183+
}
184+
if (options.has(this.javaVersion)) {
185+
request.setJavaVersion(options.valueOf(this.javaVersion));
186+
}
187+
if (options.has(this.packaging)) {
188+
request.setPackaging(options.valueOf(this.packaging));
189+
}
190+
request.setBuild(options.valueOf(this.build));
191+
request.setFormat(options.valueOf(this.format));
192+
request.setDetectType(options.has(this.build) || options.has(this.format));
193+
if (options.has(this.type)) {
194+
request.setType(options.valueOf(this.type));
195+
}
196+
if (options.has(this.output)) {
197+
request.setOutput(options.valueOf(this.output));
198+
}
199+
return request;
200+
}
201+
38202
}
39203

40204
}

0 commit comments

Comments
 (0)