All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.table.client.cli.CliOptionsParser Maven / Gradle / Ivy

Go to download

There is a newer version: 2.0-preview1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 *     http://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.apache.flink.table.client.cli;

import org.apache.flink.core.fs.Path;
import org.apache.flink.table.client.SqlClientException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Parser for command line options.
 */
public class CliOptionsParser {

	public static final Option OPTION_HELP = Option
			.builder("h")
			.required(false)
			.longOpt("help")
			.desc(
				"Show the help message with descriptions of all options.")
			.build();

	public static final Option OPTION_SESSION = Option
			.builder("s")
			.required(false)
			.longOpt("session")
			.numberOfArgs(1)
			.argName("session identifier")
			.desc(
				"The identifier for a session. 'default' is the default identifier.")
			.build();

	public static final Option OPTION_ENVIRONMENT = Option
			.builder("e")
			.required(false)
			.longOpt("environment")
			.numberOfArgs(1)
			.argName("environment file")
			.desc(
				"The environment properties to be imported into the session. " +
				"It might overwrite default environment properties.")
			.build();

	public static final Option OPTION_DEFAULTS = Option
			.builder("d")
			.required(false)
			.longOpt("defaults")
			.numberOfArgs(1)
			.argName("environment file")
			.desc(
				"The environment properties with which every new session is initialized. " +
				"Properties might be overwritten by session properties.")
			.build();

	public static final Option OPTION_JAR = Option
			.builder("j")
			.required(false)
			.longOpt("jar")
			.numberOfArgs(1)
			.argName("JAR file")
			.desc(
				"A JAR file to be imported into the session. The file might contain " +
				"user-defined classes needed for the execution of statements such as " +
				"functions, table sources, or sinks. Can be used multiple times.")
			.build();

	public static final Option OPTION_LIBRARY = Option
			.builder("l")
			.required(false)
			.longOpt("library")
			.numberOfArgs(1)
			.argName("JAR directory")
			.desc(
				"A JAR file directory with which every new session is initialized. The files might " +
				"contain user-defined classes needed for the execution of statements such as " +
				"functions, table sources, or sinks. Can be used multiple times.")
			.build();

	public static final Option OPTION_UPDATE = Option
			.builder("u")
			.required(false)
			.longOpt("update")
			.numberOfArgs(1)
			.argName("SQL update statement")
			.desc(
				"Experimental (for testing only!): Instructs the SQL Client to immediately execute " +
				"the given update statement after starting up. The process is shut down after the " +
				"statement has been submitted to the cluster and returns an appropriate return code. " +
				"Currently, this feature is only supported for INSERT INTO statements that declare " +
				"the target sink table.")
			.build();

	private static final Options EMBEDDED_MODE_CLIENT_OPTIONS = getEmbeddedModeClientOptions(new Options());
	private static final Options GATEWAY_MODE_CLIENT_OPTIONS = getGatewayModeClientOptions(new Options());
	private static final Options GATEWAY_MODE_GATEWAY_OPTIONS = getGatewayModeGatewayOptions(new Options());

	private static void buildGeneralOptions(Options options) {
		options.addOption(OPTION_HELP);
	}

	public static Options getEmbeddedModeClientOptions(Options options) {
		buildGeneralOptions(options);
		options.addOption(OPTION_SESSION);
		options.addOption(OPTION_ENVIRONMENT);
		options.addOption(OPTION_DEFAULTS);
		options.addOption(OPTION_JAR);
		options.addOption(OPTION_LIBRARY);
		options.addOption(OPTION_UPDATE);
		return options;
	}

	public static Options getGatewayModeClientOptions(Options options) {
		buildGeneralOptions(options);
		options.addOption(OPTION_SESSION);
		options.addOption(OPTION_ENVIRONMENT);
		options.addOption(OPTION_UPDATE);
		return options;
	}

	public static Options getGatewayModeGatewayOptions(Options options) {
		buildGeneralOptions(options);
		options.addOption(OPTION_DEFAULTS);
		options.addOption(OPTION_JAR);
		options.addOption(OPTION_LIBRARY);
		return options;
	}

	// --------------------------------------------------------------------------------------------
	//  Help
	// --------------------------------------------------------------------------------------------

	/**
	 * Prints the help for the client.
	 */
	public static void printHelpClient() {
		System.out.println("./sql-client [MODE] [OPTIONS]");
		System.out.println();
		System.out.println("The following options are available:");

		printHelpEmbeddedModeClient();
		printHelpGatewayModeClient();

		System.out.println();
	}

	/**
	 * Prints the help for the gateway.
	 */
	public static void printHelpGateway() {
		System.out.println("./sql-gateway [OPTIONS]");
		System.out.println();
		System.out.println("The following options are available:");

		printHelpGatewayModeGateway();

		System.out.println();
	}

	public static void printHelpEmbeddedModeClient() {
		HelpFormatter formatter = new HelpFormatter();
		formatter.setLeftPadding(5);
		formatter.setWidth(80);

		System.out.println("\nMode \"embedded\" submits Flink jobs from the local machine.");
		System.out.println("\n  Syntax: embedded [OPTIONS]");
		formatter.setSyntaxPrefix("  \"embedded\" mode options:");
		formatter.printHelp(" ", EMBEDDED_MODE_CLIENT_OPTIONS);

		System.out.println();
	}

	public static void printHelpGatewayModeClient() {
// TODO enable this once gateway mode is in place
//		HelpFormatter formatter = new HelpFormatter();
//		formatter.setLeftPadding(5);
//		formatter.setWidth(80);
//
//		System.out.println("\nIn future versions: Mode \"gateway\" mode connects to the SQL gateway for submission.");
//		System.out.println("\n  Syntax: gateway [OPTIONS]");
//		formatter.setSyntaxPrefix("  \"gateway\" mode options:");
//		formatter.printHelp(" ", GATEWAY_MODE_CLIENT_OPTIONS);
//
//		System.out.println();
	}

	public static void printHelpGatewayModeGateway() {
		HelpFormatter formatter = new HelpFormatter();
		formatter.setLeftPadding(5);
		formatter.setWidth(80);

		formatter.printHelp(" ", GATEWAY_MODE_GATEWAY_OPTIONS);

		System.out.println();
	}

	// --------------------------------------------------------------------------------------------
	//  Line Parsing
	// --------------------------------------------------------------------------------------------

	public static CliOptions parseEmbeddedModeClient(String[] args) {
		try {
			DefaultParser parser = new DefaultParser();
			CommandLine line = parser.parse(EMBEDDED_MODE_CLIENT_OPTIONS, args, true);
			return new CliOptions(
				line.hasOption(CliOptionsParser.OPTION_HELP.getOpt()),
				checkSessionId(line),
				checkUrl(line, CliOptionsParser.OPTION_ENVIRONMENT),
				checkUrl(line, CliOptionsParser.OPTION_DEFAULTS),
				checkUrls(line, CliOptionsParser.OPTION_JAR),
				checkUrls(line, CliOptionsParser.OPTION_LIBRARY),
				line.getOptionValue(CliOptionsParser.OPTION_UPDATE.getOpt())
			);
		}
		catch (ParseException e) {
			throw new SqlClientException(e.getMessage());
		}
	}

	public static CliOptions parseGatewayModeClient(String[] args) {
		try {
			DefaultParser parser = new DefaultParser();
			CommandLine line = parser.parse(GATEWAY_MODE_CLIENT_OPTIONS, args, true);
			return new CliOptions(
				line.hasOption(CliOptionsParser.OPTION_HELP.getOpt()),
				checkSessionId(line),
				checkUrl(line, CliOptionsParser.OPTION_ENVIRONMENT),
				null,
				checkUrls(line, CliOptionsParser.OPTION_JAR),
				checkUrls(line, CliOptionsParser.OPTION_LIBRARY),
				line.getOptionValue(CliOptionsParser.OPTION_UPDATE.getOpt())
			);
		}
		catch (ParseException e) {
			throw new SqlClientException(e.getMessage());
		}
	}

	public static CliOptions parseGatewayModeGateway(String[] args) {
		try {
			DefaultParser parser = new DefaultParser();
			CommandLine line = parser.parse(GATEWAY_MODE_GATEWAY_OPTIONS, args, true);
			return new CliOptions(
				line.hasOption(CliOptionsParser.OPTION_HELP.getOpt()),
				null,
				null,
				checkUrl(line, CliOptionsParser.OPTION_DEFAULTS),
				checkUrls(line, CliOptionsParser.OPTION_JAR),
				checkUrls(line, CliOptionsParser.OPTION_LIBRARY),
				null
			);
		}
		catch (ParseException e) {
			throw new SqlClientException(e.getMessage());
		}
	}

	// --------------------------------------------------------------------------------------------

	private static URL checkUrl(CommandLine line, Option option) {
		final List urls = checkUrls(line, option);
		if (urls != null && !urls.isEmpty()) {
			return urls.get(0);
		}
		return null;
	}

	private static List checkUrls(CommandLine line, Option option) {
		if (line.hasOption(option.getOpt())) {
			final String[] urls = line.getOptionValues(option.getOpt());
			return Arrays.stream(urls)
				.distinct()
				.map((url) -> {
					try {
						return Path.fromLocalFile(new File(url).getAbsoluteFile()).toUri().toURL();
					} catch (Exception e) {
						throw new SqlClientException("Invalid path for option '" + option.getLongOpt() + "': " + url, e);
					}
				})
				.collect(Collectors.toList());
		}
		return null;
	}

	private static String checkSessionId(CommandLine line) {
		final String sessionId = line.getOptionValue(CliOptionsParser.OPTION_SESSION.getOpt());
		if (sessionId != null && !sessionId.matches("[a-zA-Z0-9_\\-.]+")) {
			throw new SqlClientException("Session identifier must only consists of 'a-zA-Z0-9_-.'.");
		}
		return sessionId;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy