spring InitCommand 源码

  • 2022-08-12
  • 浏览 (362)

springboot InitCommand 代码

文件路径:/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitCommand.java

/*
 * Copyright 2012-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import org.springframework.boot.cli.command.Command;
import org.springframework.boot.cli.command.HelpExample;
import org.springframework.boot.cli.command.OptionParsingCommand;
import org.springframework.boot.cli.command.options.OptionHandler;
import org.springframework.boot.cli.command.status.ExitStatus;
import org.springframework.boot.cli.util.Log;
import org.springframework.util.Assert;

/**
 * {@link Command} that initializes a project using Spring initializr.
 *
 * @author Stephane Nicoll
 * @author Eddú Meléndez
 * @author Vignesh Thangavel Ilangovan
 * @since 1.2.0
 */
public class InitCommand extends OptionParsingCommand {

	public InitCommand() {
		this(new InitOptionHandler(new InitializrService()));
	}

	public InitCommand(InitOptionHandler handler) {
		super("init", "Initialize a new project using Spring Initializr (start.spring.io)", handler);
	}

	@Override
	public String getUsageHelp() {
		return "[options] [location]";
	}

	@Override
	public Collection<HelpExample> getExamples() {
		List<HelpExample> examples = new ArrayList<>();
		examples.add(new HelpExample("To list all the capabilities of the service", "spring init --list"));
		examples.add(new HelpExample("To creates a default project", "spring init"));
		examples.add(new HelpExample("To create a web my-app.zip", "spring init -d=web my-app.zip"));
		examples.add(new HelpExample("To create a web/data-jpa gradle project unpacked",
				"spring init -d=web,jpa --build=gradle my-dir"));
		return examples;
	}

	/**
	 * {@link OptionHandler} for {@link InitCommand}.
	 */
	static class InitOptionHandler extends OptionHandler {

		/**
		 * Mapping from camelCase options advertised by the service to our kebab-case
		 * options.
		 */
		private static final Map<String, String> CAMEL_CASE_OPTIONS;
		static {
			Map<String, String> options = new HashMap<>();
			options.put("--groupId", "--group-id");
			options.put("--artifactId", "--artifact-id");
			options.put("--packageName", "--package-name");
			options.put("--javaVersion", "--java-version");
			options.put("--bootVersion", "--boot-version");
			CAMEL_CASE_OPTIONS = Collections.unmodifiableMap(options);
		}

		private final ServiceCapabilitiesReportGenerator serviceCapabilitiesReport;

		private final ProjectGenerator projectGenerator;

		private OptionSpec<String> target;

		private OptionSpec<Void> listCapabilities;

		private OptionSpec<String> groupId;

		private OptionSpec<String> artifactId;

		private OptionSpec<String> version;

		private OptionSpec<String> name;

		private OptionSpec<String> description;

		private OptionSpec<String> packageName;

		private OptionSpec<String> type;

		private OptionSpec<String> packaging;

		private OptionSpec<String> build;

		private OptionSpec<String> format;

		private OptionSpec<String> javaVersion;

		private OptionSpec<String> language;

		private OptionSpec<String> bootVersion;

		private OptionSpec<String> dependencies;

		private OptionSpec<Void> extract;

		private OptionSpec<Void> force;

		InitOptionHandler(InitializrService initializrService) {
			super(InitOptionHandler::processArgument);
			this.serviceCapabilitiesReport = new ServiceCapabilitiesReportGenerator(initializrService);
			this.projectGenerator = new ProjectGenerator(initializrService);
		}

		@Override
		protected void options() {
			this.target = option(Arrays.asList("target"), "URL of the service to use").withRequiredArg()
					.defaultsTo(ProjectGenerationRequest.DEFAULT_SERVICE_URL);
			this.listCapabilities = option(Arrays.asList("list"),
					"List the capabilities of the service. Use it to discover the "
							+ "dependencies and the types that are available");
			projectGenerationOptions();
			otherOptions();
		}

		private void projectGenerationOptions() {
			this.groupId = option(Arrays.asList("group-id", "g"), "Project coordinates (for example 'org.test')")
					.withRequiredArg();
			this.artifactId = option(Arrays.asList("artifact-id", "a"),
					"Project coordinates; infer archive name (for example 'test')").withRequiredArg();
			this.version = option(Arrays.asList("version", "v"), "Project version (for example '0.0.1-SNAPSHOT')")
					.withRequiredArg();
			this.name = option(Arrays.asList("name", "n"), "Project name; infer application name").withRequiredArg();
			this.description = option("description", "Project description").withRequiredArg();
			this.packageName = option(Arrays.asList("package-name"), "Package name").withRequiredArg();
			this.type = option(Arrays.asList("type", "t"),
					"Project type. Not normally needed if you use --build "
							+ "and/or --format. Check the capabilities of the service (--list) for more details")
									.withRequiredArg();
			this.packaging = option(Arrays.asList("packaging", "p"), "Project packaging (for example 'jar')")
					.withRequiredArg();
			this.build = option("build", "Build system to use (for example 'maven' or 'gradle')").withRequiredArg()
					.defaultsTo("maven");
			this.format = option("format", "Format of the generated content (for example 'build' for a build file, "
					+ "'project' for a project archive)").withRequiredArg().defaultsTo("project");
			this.javaVersion = option(Arrays.asList("java-version", "j"), "Language level (for example '1.8')")
					.withRequiredArg();
			this.language = option(Arrays.asList("language", "l"), "Programming language  (for example 'java')")
					.withRequiredArg();
			this.bootVersion = option(Arrays.asList("boot-version", "b"),
					"Spring Boot version (for example '1.2.0.RELEASE')").withRequiredArg();
			this.dependencies = option(Arrays.asList("dependencies", "d"),
					"Comma-separated list of dependency identifiers to include in the generated project")
							.withRequiredArg();
		}

		private void otherOptions() {
			this.extract = option(Arrays.asList("extract", "x"),
					"Extract the project archive. Inferred if a location is specified without an extension");
			this.force = option(Arrays.asList("force", "f"), "Force overwrite of existing files");
		}

		@Override
		protected ExitStatus run(OptionSet options) throws Exception {
			try {
				if (options.has(this.listCapabilities)) {
					generateReport(options);
				}
				else {
					generateProject(options);
				}
				return ExitStatus.OK;
			}
			catch (ReportableException ex) {
				Log.error(ex.getMessage());
				return ExitStatus.ERROR;
			}
			catch (Exception ex) {
				Log.error(ex);
				return ExitStatus.ERROR;
			}
		}

		private void generateReport(OptionSet options) throws IOException {
			Log.info(this.serviceCapabilitiesReport.generate(options.valueOf(this.target)));
		}

		protected void generateProject(OptionSet options) throws IOException {
			ProjectGenerationRequest request = createProjectGenerationRequest(options);
			this.projectGenerator.generateProject(request, options.has(this.force));
		}

		protected ProjectGenerationRequest createProjectGenerationRequest(OptionSet options) {
			List<?> nonOptionArguments = new ArrayList<Object>(options.nonOptionArguments());
			Assert.isTrue(nonOptionArguments.size() <= 1, "Only the target location may be specified");
			ProjectGenerationRequest request = new ProjectGenerationRequest();
			request.setServiceUrl(options.valueOf(this.target));
			if (options.has(this.bootVersion)) {
				request.setBootVersion(options.valueOf(this.bootVersion));
			}
			if (options.has(this.dependencies)) {
				for (String dep : options.valueOf(this.dependencies).split(",")) {
					request.getDependencies().add(dep.trim());
				}
			}
			if (options.has(this.javaVersion)) {
				request.setJavaVersion(options.valueOf(this.javaVersion));
			}
			if (options.has(this.packageName)) {
				request.setPackageName(options.valueOf(this.packageName));
			}
			request.setBuild(options.valueOf(this.build));
			request.setFormat(options.valueOf(this.format));
			request.setDetectType(options.has(this.build) || options.has(this.format));
			if (options.has(this.type)) {
				request.setType(options.valueOf(this.type));
			}
			if (options.has(this.packaging)) {
				request.setPackaging(options.valueOf(this.packaging));
			}
			if (options.has(this.language)) {
				request.setLanguage(options.valueOf(this.language));
			}
			if (options.has(this.groupId)) {
				request.setGroupId(options.valueOf(this.groupId));
			}
			if (options.has(this.artifactId)) {
				request.setArtifactId(options.valueOf(this.artifactId));
			}
			if (options.has(this.name)) {
				request.setName(options.valueOf(this.name));
			}
			if (options.has(this.version)) {
				request.setVersion(options.valueOf(this.version));
			}
			if (options.has(this.description)) {
				request.setDescription(options.valueOf(this.description));
			}
			request.setExtract(options.has(this.extract));
			if (nonOptionArguments.size() == 1) {
				String output = (String) nonOptionArguments.get(0);
				request.setOutput(output);
			}
			return request;
		}

		private static String processArgument(String argument) {
			for (Map.Entry<String, String> entry : CAMEL_CASE_OPTIONS.entrySet()) {
				String name = entry.getKey();
				if (argument.startsWith(name + " ") || argument.startsWith(name + "=")) {
					return entry.getValue() + argument.substring(name.length());
				}
			}
			return argument;
		}

	}

}

相关信息

spring 源码目录

相关文章

spring Dependency 源码

spring InitializrService 源码

spring InitializrServiceMetadata 源码

spring ProjectGenerationRequest 源码

spring ProjectGenerationResponse 源码

spring ProjectGenerator 源码

spring ProjectType 源码

spring ReportableException 源码

spring ServiceCapabilitiesReportGenerator 源码

spring package-info 源码

0  赞