| /* |
| * Copyright 2017 HugeGraph Authors |
| * |
| * 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 com.baidu.hugegraph.cmd; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import com.baidu.hugegraph.structure.constant.HugeType; |
| import com.baidu.hugegraph.util.E; |
| import com.beust.jcommander.IParameterValidator; |
| import com.beust.jcommander.IStringConverter; |
| import com.beust.jcommander.Parameter; |
| import com.beust.jcommander.ParameterException; |
| import com.beust.jcommander.Parameters; |
| import com.beust.jcommander.ParametersDelegate; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| |
| public class SubCommands { |
| |
| private Map<String, Object> commands; |
| |
| public SubCommands() { |
| this.commands = new HashMap<>(); |
| this.initSubCommands(); |
| } |
| |
| private void initSubCommands() { |
| this.commands.put("backup", new Backup()); |
| this.commands.put("restore", new Restore()); |
| this.commands.put("schedule-backup", new ScheduleBackup()); |
| this.commands.put("dump", new DumpGraph()); |
| this.commands.put("graph-list", new GraphList()); |
| this.commands.put("graph-get", new GraphGet()); |
| this.commands.put("graph-clear", new GraphClear()); |
| this.commands.put("graph-mode-set", new GraphModeSet()); |
| this.commands.put("graph-mode-get", new GraphModeGet()); |
| this.commands.put("gremlin-execute", new Gremlin()); |
| this.commands.put("gremlin-schedule", new GremlinJob()); |
| this.commands.put("task-list", new TaskList()); |
| this.commands.put("task-get", new TaskGet()); |
| this.commands.put("task-delete", new TaskDelete()); |
| this.commands.put("deploy", new Deploy()); |
| this.commands.put("start-all", new StartAll()); |
| this.commands.put("clear", new Clear()); |
| this.commands.put("stop-all", new StopAll()); |
| this.commands.put("help", new Help()); |
| } |
| |
| public Map<String, Object> commands() { |
| return this.commands; |
| } |
| |
| @Parameters(commandDescription = "Schedule backup task") |
| public class ScheduleBackup { |
| |
| @Parameter(names = {"--interval"}, arity = 1, |
| description = |
| "The interval of backup, format is: \"a b c d e\"." + |
| " 'a' means minute (0 - 59)," + |
| " 'b' means hour (0 - 23)," + |
| " 'c' means day of month (1 - 31)," + |
| " 'd' means month (1 - 12)," + |
| " 'e' means day of week (0 - 6) (Sunday=0)," + |
| " \"*\" means all") |
| public String interval = "0,0,*,*,*"; |
| |
| @Parameter(names = {"--backup-num"}, arity = 1, |
| validateWith = {UrlValidator.class}, |
| description = "The number of latest backups to keep") |
| public int num = 3; |
| |
| @Parameter(names = {"--directory", "-d"}, arity = 1, |
| validateWith = {UrlValidator.class}, required = true, |
| description = "The directory of backups stored") |
| public String directory; |
| } |
| |
| @Parameters(commandDescription = "Backup graph schema/data to files") |
| public class Backup extends BackupRestore { |
| |
| @Parameter(names = {"--directory", "-d"}, arity = 1, |
| description = "Directory to store graph schema/data") |
| public String directory = "./"; |
| |
| public String directory() { |
| return this.directory; |
| } |
| } |
| |
| @Parameters(commandDescription = "Restore graph schema/data from files") |
| public class Restore extends BackupRestore { |
| |
| @ParametersDelegate |
| private ExistDirectory directory = new ExistDirectory(); |
| |
| public String directory() { |
| return this.directory.directory; |
| } |
| } |
| |
| @Parameters(commandDescription = "Dump graph to files") |
| public class DumpGraph { |
| |
| @ParametersDelegate |
| private Retry retry = new Retry(); |
| |
| @Parameter(names = {"--directory", "-d"}, arity = 1, |
| description = "Directory to store graph data") |
| public String directory = "./"; |
| |
| public int retry() { |
| return this.retry.retry; |
| } |
| |
| public String directory() { |
| return this.directory; |
| } |
| } |
| |
| @Parameters(commandDescription = "List all graphs") |
| public class GraphList { |
| } |
| |
| @Parameters(commandDescription = "Get graph info") |
| public class GraphGet { |
| |
| @ParametersDelegate |
| private GraphName graph = new GraphName(); |
| |
| public String graph() { |
| return this.graph.graphName; |
| } |
| } |
| |
| @Parameters(commandDescription = "Clear graph schema and data") |
| public class GraphClear { |
| |
| @ParametersDelegate |
| private GraphName graph = new GraphName(); |
| |
| @ParametersDelegate |
| private ConfirmMessage message = new ConfirmMessage(); |
| |
| public String graph() { |
| return this.graph.graphName; |
| } |
| |
| public String confirmMessage() { |
| return this.message.confirmMessage; |
| } |
| } |
| |
| @Parameters(commandDescription = "Set graph mode") |
| public class GraphModeSet { |
| |
| @ParametersDelegate |
| private GraphName graph = new GraphName(); |
| |
| @ParametersDelegate |
| private RestoreFlag restoreFlag = new RestoreFlag(); |
| |
| public String graph() { |
| return this.graph.graphName; |
| } |
| |
| public boolean restoreFlag() { |
| return this.restoreFlag.restoreFlag; |
| } |
| } |
| |
| @Parameters(commandDescription = "Get graph mode") |
| public class GraphModeGet { |
| |
| @ParametersDelegate |
| private GraphName graph = new GraphName(); |
| |
| public String graph() { |
| return this.graph.graphName; |
| } |
| } |
| |
| @Parameters(commandDescription = "Execute Gremlin statements") |
| public class Gremlin { |
| |
| @ParametersDelegate |
| private GremlinScript script = new GremlinScript(); |
| |
| @ParametersDelegate |
| private Language language = new Language(); |
| |
| @ParametersDelegate |
| private Bindings bindings = new Bindings(); |
| |
| @ParametersDelegate |
| private Aliases aliases = new Aliases(); |
| |
| public String script() { |
| return this.script.script; |
| } |
| |
| public String language() { |
| return this.language.language; |
| } |
| |
| public Map<String, String> bindings() { |
| return this.bindings.bindings; |
| } |
| |
| public Map<String, String> aliases() { |
| return this.aliases.aliases; |
| } |
| } |
| |
| @Parameters(commandDescription = "Execute Gremlin statements as " + |
| "asynchronous job") |
| public class GremlinJob { |
| |
| @ParametersDelegate |
| private GremlinScript script = new GremlinScript(); |
| |
| @ParametersDelegate |
| private Language language = new Language(); |
| |
| @ParametersDelegate |
| private Bindings bindings = new Bindings(); |
| |
| public String script() { |
| return this.script.script; |
| } |
| |
| public String language() { |
| return this.language.language; |
| } |
| |
| public Map<String, String> bindings() { |
| return this.bindings.bindings; |
| } |
| } |
| |
| @Parameters(commandDescription = "List tasks") |
| public class TaskList { |
| |
| @ParametersDelegate |
| private TaskStatus status = new TaskStatus(); |
| |
| @ParametersDelegate |
| private Limit limit = new Limit(); |
| |
| public String status() { |
| return this.status.status.toUpperCase(); |
| } |
| |
| public long limit() { |
| return this.limit.limit; |
| } |
| } |
| |
| @Parameters(commandDescription = "Get task info") |
| public class TaskGet { |
| |
| @ParametersDelegate |
| private TaskId taskId = new TaskId(); |
| |
| public long taskId() { |
| return this.taskId.taskId; |
| } |
| } |
| |
| @Parameters(commandDescription = "Delete task") |
| public class TaskDelete { |
| |
| @ParametersDelegate |
| private TaskId taskId = new TaskId(); |
| |
| public long taskId() { |
| return this.taskId.taskId; |
| } |
| } |
| |
| @Parameters(commandDescription = "Install HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public class Deploy { |
| |
| @ParametersDelegate |
| private Version version = new Version(); |
| |
| @ParametersDelegate |
| public InstallPath path = new InstallPath(); |
| |
| @ParametersDelegate |
| public DownloadURL url = new DownloadURL(); |
| } |
| |
| @Parameters(commandDescription = "Start HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public class StartAll { |
| |
| @ParametersDelegate |
| private Version version = new Version(); |
| |
| @ParametersDelegate |
| public InstallPath path = new InstallPath(); |
| } |
| |
| @Parameters(commandDescription = "Clear HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public class Clear { |
| |
| @ParametersDelegate |
| public InstallPath path = new InstallPath(); |
| } |
| |
| @Parameters(commandDescription = "Stop HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public class StopAll { |
| } |
| |
| @Parameters(commandDescription = "Print usage") |
| public class Help { |
| } |
| |
| public class BackupRestore { |
| |
| @ParametersDelegate |
| private HugeTypes types = new HugeTypes(); |
| |
| @ParametersDelegate |
| private Retry retry = new Retry(); |
| |
| public List<HugeType> types() { |
| return this.types.types; |
| } |
| |
| public int retry() { |
| return this.retry.retry; |
| } |
| } |
| |
| public static class Url { |
| |
| @Parameter(names = {"--url"}, arity = 1, |
| validateWith = {UrlValidator.class}, |
| description = "The URL of HugeGraph-Server url") |
| public String url = "http://127.0.0.1:8080"; |
| } |
| |
| public static class Graph { |
| |
| @Parameter(names = {"--graph"}, arity = 1, |
| description = "Name of graph") |
| public String graph = "hugegraph"; |
| } |
| |
| public static class Username { |
| |
| @Parameter(names = {"--user"}, arity = 1, |
| description = "User Name") |
| public String username; |
| } |
| |
| public static class Password { |
| |
| @Parameter(names = {"--password"}, arity = 1, |
| description = "Password of user") |
| public String password; |
| } |
| |
| public static class GraphName { |
| |
| @Parameter(names = {"--graph-name"}, arity = 1, |
| description = "Name of graph") |
| public String graphName = "hugegraph"; |
| } |
| |
| public class HugeTypes { |
| |
| @Parameter(names = {"--huge-types", "-t"}, |
| listConverter = HugeTypeListConverter.class, |
| required = true, |
| description = "Type of schema/data. " + |
| "Concat with ',' if more than one. " + |
| "'all' means 'vertex,edge,vertex_label," + |
| "edge_label,property_key,index_label'") |
| public List<HugeType> types; |
| } |
| |
| public class ExistDirectory { |
| |
| @Parameter(names = {"--directory", "-d"}, arity = 1, |
| validateWith = {DirectoryValidator.class}, |
| description = "Directory of graph schema/data") |
| public String directory = "./"; |
| } |
| |
| public class InstallPath { |
| |
| @Parameter(names = {"-p"}, arity = 1, required = true, |
| description = "Install path of HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public String directory = null; |
| } |
| |
| public class DownloadURL { |
| |
| @Parameter(names = {"-u"}, arity = 1, |
| description = "Download url prefix path of " + |
| "HugeGraph-Server and HugeGraph-Studio") |
| public String url = null; |
| } |
| |
| public class ConfirmMessage { |
| |
| @Parameter(names = {"--confirm-message", "-c"}, arity = 1, |
| description = "Confirm message of graph clear", |
| required = true) |
| public String confirmMessage; |
| } |
| |
| public class RestoreFlag { |
| |
| @Parameter(names = {"--restore", "-r"}, arity = 1, |
| description = "Restore flag", |
| required = true) |
| public boolean restoreFlag; |
| } |
| |
| public class GremlinScript { |
| |
| @Parameter(names = {"--script", "-s"}, arity = 1, |
| required = true, |
| description = "Script to be executed") |
| public String script; |
| } |
| |
| public class Language { |
| |
| @Parameter(names = {"--language", "-l"}, arity = 1, |
| description = "Gremlin script language") |
| public String language = "gremlin-groovy"; |
| } |
| |
| public class Bindings { |
| |
| @Parameter(names = {"--bindings", "-b"}, arity = 1, |
| converter = MapConverter.class, |
| description = "Gremlin bindings, valid format is: " + |
| "'key1=value1,key2=value2...'") |
| public Map<String, String> bindings = ImmutableMap.of(); |
| } |
| |
| public class Aliases { |
| |
| @Parameter(names = {"--aliases", "-a"}, arity = 1, |
| converter = MapConverter.class, |
| description = "Gremlin aliases, valid format is: " + |
| "'key1=value1,key2=value2...'") |
| public Map<String, String> aliases = ImmutableMap.of(); |
| } |
| |
| public class Version { |
| |
| @Parameter(names = {"-v"}, arity = 1, required = true, |
| description = "Version of HugeGraph-Server and " + |
| "HugeGraph-Studio") |
| public String version; |
| } |
| |
| public class Retry { |
| |
| @Parameter(names = {"--retry"}, arity = 1, |
| validateWith = {PositiveValidator.class}, |
| description = "Retry times, default is 3") |
| public int retry = 3; |
| } |
| |
| public class Limit { |
| |
| @Parameter(names = {"--limit"}, arity = 1, |
| validateWith = {PositiveValidator.class}, |
| description = "Limit number, no limit if not provided") |
| public long limit = -1; |
| } |
| |
| public class TaskStatus { |
| |
| @Parameter(names = {"--status"}, arity = 1, |
| validateWith = TaskStatusValidator.class, |
| description = "Status of task") |
| public String status = null; |
| } |
| |
| public class TaskId { |
| |
| @Parameter(names = {"--task-id"}, arity = 1, required = true, |
| validateWith = {PositiveValidator.class}, |
| description = "Task id") |
| private long taskId; |
| } |
| |
| public static class HugeTypeListConverter |
| implements IStringConverter<List<HugeType>> { |
| |
| @Override |
| public List<HugeType> convert(String value) { |
| E.checkArgument(value != null && !value.isEmpty(), |
| "HugeType can't be null or empty"); |
| String[] types = value.split(","); |
| if (types.length == 1 && types[0].equalsIgnoreCase("all")) { |
| return ImmutableList.of(HugeType.PROPERTY_KEY, |
| HugeType.VERTEX_LABEL, |
| HugeType.EDGE_LABEL, |
| HugeType.INDEX_LABEL, |
| HugeType.VERTEX, |
| HugeType.EDGE); |
| } |
| List<HugeType> hugeTypes = new ArrayList<>(); |
| for (String type : types) { |
| try { |
| hugeTypes.add(HugeType.valueOf(type.toUpperCase())); |
| } catch (IllegalArgumentException e) { |
| throw new ParameterException(String.format( |
| "Invalid --type '%s', valid value is 'all' or " + |
| "combination of 'vertex,edge,vertex_label," + |
| "edge_label,property_key,index_label'", type)); |
| } |
| } |
| return hugeTypes; |
| } |
| } |
| |
| public static class MapConverter |
| implements IStringConverter<Map<String, String>> { |
| |
| @Override |
| public Map<String, String> convert(String value) { |
| E.checkArgument(value != null && !value.isEmpty(), |
| "HugeType can't be null or empty"); |
| String[] equals = value.split(","); |
| Map<String, String> result = new HashMap<>(); |
| for (String equal : equals) { |
| String[] kv = equal.split("="); |
| E.checkArgument(kv.length == 2, |
| "Map arguments format should be key=value, " + |
| "but got '%s'", equal); |
| result.put(kv[0], kv[1]); |
| } |
| return result; |
| } |
| } |
| |
| public static class TaskStatusValidator implements IParameterValidator { |
| |
| private static final Set<String> STATUSES = ImmutableSet.of( |
| "UNKNOWN", "NEW", "QUEUED", "RESTORING", "RUNNING", |
| "SUCCESS", "CANCELLED", "FAILED" |
| ); |
| |
| @Override |
| public void validate(String name, String value) { |
| System.out.println(value.toUpperCase()); |
| System.out.println(STATUSES.contains(value.toUpperCase())); |
| if (!STATUSES.contains(value.toUpperCase())) { |
| throw new ParameterException(String.format( |
| "Invalid --status '%s', valid value is %s", |
| value, STATUSES)); |
| } |
| } |
| } |
| |
| public static class UrlValidator implements IParameterValidator { |
| |
| @Override |
| public void validate(String name, String value) { |
| String regex = "^((https|http|ftp|rtsp|mms)?://)" |
| + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" |
| + "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP URL, like: 10.0.0.1 |
| + "|" // Or domain name |
| + "([0-9a-z_!~*'()-]+\\.)*" // Third level, like: www. |
| + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // Second level |
| + "[a-z]{2,6})" // First level, like: com or museum |
| + "(:[0-9]{1,4})?"; // Port, like: 8080 |
| if (!value.matches(regex)) { |
| throw new ParameterException(String.format( |
| "Invalid value of argument '%s': '%s'", name, value)); |
| } |
| } |
| } |
| |
| public static class DirectoryValidator implements IParameterValidator { |
| |
| @Override |
| public void validate(String name, String value) { |
| File file = new File(value); |
| if (!file.exists() || !file.isDirectory()) { |
| throw new ParameterException(String.format( |
| "Invalid value of argument '%s': '%s'", name, value)); |
| } |
| } |
| } |
| |
| public static class PositiveValidator implements IParameterValidator { |
| |
| @Override |
| public void validate(String name, String value) { |
| int retry = Integer.parseInt(value); |
| if (retry <= 0) { |
| throw new ParameterException( |
| "Parameter " + name + " should be positive, " + |
| "but got " + value); |
| } |
| } |
| } |
| } |