PageRenderTime 45ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/cli/src/main/java/com/gooddata/processor/GdcDI.java

https://github.com/chrbayer84/GoodData-CL
Java | 1528 lines | 1114 code | 114 blank | 300 comment | 308 complexity | 2b2286b76114e6c8d09e260f4e54f8e8 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2009, GoodData Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without modification, are permitted provided
  5. * that the following conditions are met:
  6. *
  7. * * Redistributions of source code must retain the above copyright notice, this list of conditions and
  8. * the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  10. * and the following disclaimer in the documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the GoodData Corporation nor the names of its contributors may be used to endorse
  12. * or promote products derived from this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  15. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  16. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. package com.gooddata.processor;
  24. import com.gooddata.Constants;
  25. import com.gooddata.connector.*;
  26. import com.gooddata.exception.*;
  27. import com.gooddata.integration.model.Column;
  28. import com.gooddata.integration.model.SLI;
  29. import com.gooddata.integration.rest.GdcRESTApiWrapper;
  30. import com.gooddata.integration.rest.MetadataObject;
  31. import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
  32. import com.gooddata.modeling.model.SourceSchema;
  33. import com.gooddata.naming.N;
  34. import com.gooddata.processor.parser.DIScriptParser;
  35. import com.gooddata.processor.parser.ParseException;
  36. import com.gooddata.util.DatabaseToCsv;
  37. import com.gooddata.util.FileUtil;
  38. import com.gooddata.util.StringUtil;
  39. import org.apache.commons.cli.*;
  40. import org.apache.log4j.Logger;
  41. import org.apache.log4j.PropertyConfigurator;
  42. import org.joda.time.DateTimeZone;
  43. import java.io.*;
  44. import java.sql.SQLException;
  45. import java.util.ArrayList;
  46. import java.util.List;
  47. import java.util.Properties;
  48. /**
  49. * The GoodData Data Integration CLI processor.
  50. *
  51. * @author jiri.zaloudek
  52. * @author Zdenek Svoboda <zd@gooddata.org>
  53. * @version 1.0
  54. */
  55. public class GdcDI implements Executor {
  56. private static Logger l = Logger.getLogger(GdcDI.class);
  57. //Options data
  58. public static String[] CLI_PARAM_HELP = {"help", "H"};
  59. public static String[] CLI_PARAM_USERNAME = {"username", "u"};
  60. public static String[] CLI_PARAM_PASSWORD = {"password", "p"};
  61. public static String[] CLI_PARAM_HOST = {"host", "h"};
  62. public static String[] CLI_PARAM_FTP_HOST = {"ftphost", "f"};
  63. public static String[] CLI_PARAM_PROJECT = {"project", "i"};
  64. public static String[] CLI_PARAM_PROTO = {"proto", "t"};
  65. public static String[] CLI_PARAM_INSECURE = {"insecure", "s"};
  66. public static String[] CLI_PARAM_EXECUTE = {"execute", "e"};
  67. public static String[] CLI_PARAM_VERSION = {"version", "V"};
  68. public static String[] CLI_PARAM_DEFAULT_DATE_FOREIGN_KEY = {"default-date-fk", "D"};
  69. public static String[] CLI_PARAM_HTTP_PROXY_HOST = {"proxyhost", "K"};
  70. public static String[] CLI_PARAM_HTTP_PROXY_PORT = {"proxyport", "L"};
  71. public static String[] CLI_PARAM_HTTP_PORT = {"port", "S"};
  72. public static String[] CLI_PARAM_FTP_PORT = {"ftpport", "O"};
  73. public static String[] CLI_PARAM_HTTP_PROXY_USERNAME = {"proxyusername", "U"};
  74. public static String[] CLI_PARAM_HTTP_PROXY_PASSWORD = {"proxypassword", "P"};
  75. public static String[] CLI_PARAM_TIMEZONE = {"timezone", "T"};
  76. public static String[] CLI_PARAM_AUTHORIZATION_TOKEN = {"authtoken", "a"};
  77. public static String CLI_PARAM_SCRIPT = "script";
  78. private static String DEFAULT_PROPERTIES = "gdi.properties";
  79. // Command line options
  80. private static Options ops = new Options();
  81. public static Option[] Options = {
  82. new Option(CLI_PARAM_HELP[1], CLI_PARAM_HELP[0], false, "Print command reference"),
  83. new Option(CLI_PARAM_USERNAME[1], CLI_PARAM_USERNAME[0], true, "GoodData username"),
  84. new Option(CLI_PARAM_PASSWORD[1], CLI_PARAM_PASSWORD[0], true, "GoodData password"),
  85. new Option(CLI_PARAM_AUTHORIZATION_TOKEN[1], CLI_PARAM_AUTHORIZATION_TOKEN[0], true, "GoodData project creation authorization token."),
  86. new Option(CLI_PARAM_HTTP_PROXY_HOST[1], CLI_PARAM_HTTP_PROXY_HOST[0], true, "HTTP proxy hostname."),
  87. new Option(CLI_PARAM_HTTP_PROXY_PORT[1], CLI_PARAM_HTTP_PROXY_PORT[0], true, "HTTP proxy port."),
  88. new Option(CLI_PARAM_HTTP_PORT[1], CLI_PARAM_HTTP_PORT[0], true, "HTTP port."),
  89. new Option(CLI_PARAM_FTP_PORT[1], CLI_PARAM_FTP_PORT[0], true, "Data stage port (deprecated)"),
  90. new Option(CLI_PARAM_HTTP_PROXY_USERNAME[1], CLI_PARAM_HTTP_PROXY_USERNAME[0], true, "HTTP proxy username."),
  91. new Option(CLI_PARAM_HTTP_PROXY_PASSWORD[1], CLI_PARAM_HTTP_PROXY_PASSWORD[0], true, "HTTP proxy password."),
  92. new Option(CLI_PARAM_HOST[1], CLI_PARAM_HOST[0], true, "GoodData host"),
  93. new Option(CLI_PARAM_FTP_HOST[1], CLI_PARAM_FTP_HOST[0], true, "GoodData data stage host (deprecated)"),
  94. new Option(CLI_PARAM_PROJECT[1], CLI_PARAM_PROJECT[0], true, "GoodData project identifier (a string like nszfbgkr75otujmc4smtl6rf5pnmz9yl)"),
  95. new Option(CLI_PARAM_PROTO[1], CLI_PARAM_PROTO[0], true, "HTTP or HTTPS (deprecated)"),
  96. new Option(CLI_PARAM_INSECURE[1], CLI_PARAM_INSECURE[0], false, "Disable encryption"),
  97. new Option(CLI_PARAM_VERSION[1], CLI_PARAM_VERSION[0], false, "Prints the tool version."),
  98. new Option(CLI_PARAM_TIMEZONE[1], CLI_PARAM_TIMEZONE[0], true, "Specify the default timezone (the computer timezone is the default)."),
  99. new Option(CLI_PARAM_EXECUTE[1], CLI_PARAM_EXECUTE[0], true, "Commands and params to execute before the commands in provided files"),
  100. new Option(CLI_PARAM_DEFAULT_DATE_FOREIGN_KEY[1], CLI_PARAM_DEFAULT_DATE_FOREIGN_KEY[0], true, "Foreign key to represent an 'unknown' date")
  101. };
  102. private CliParams cliParams = null;
  103. private Connector[] connectors = null;
  104. private ProcessingContext context = new ProcessingContext();
  105. private boolean finishedSucessfuly = false;
  106. private static long LOCK_EXPIRATION_TIME = 1000 * 3600; // 1 hour
  107. private final static String BUILD_NUMBER = "";
  108. public GdcDI(CommandLine ln, Properties defaults) {
  109. try {
  110. cliParams = parse(ln, defaults);
  111. if(cliParams.containsKey(CLI_PARAM_TIMEZONE[0])) {
  112. String timezone = cliParams.get(CLI_PARAM_TIMEZONE[0]);
  113. if(timezone != null && timezone.length()>0) {
  114. try {
  115. DateTimeZone.setDefault(DateTimeZone.forID(timezone));
  116. }
  117. catch (IllegalArgumentException e) {
  118. throw new InvalidArgumentException("Invalid timezone: '" + timezone+"'.");
  119. }
  120. }
  121. else {
  122. DateTimeZone.setDefault(DateTimeZone.forID("UTC"));
  123. }
  124. }
  125. if(cliParams.containsKey(CLI_PARAM_HTTP_PORT[0])) {
  126. String httpPortString = cliParams.get(CLI_PARAM_HTTP_PORT[0]);
  127. int httpPort = 0;
  128. try {
  129. httpPort = Integer.parseInt(httpPortString);
  130. }
  131. catch(NumberFormatException e) {
  132. throw new InvalidArgumentException("Invalid HTTP port value: '" + httpPortString+"'.");
  133. }
  134. cliParams.setHttpConfig(new NamePasswordConfiguration(
  135. cliParams.containsKey(CLI_PARAM_INSECURE[0]) ? "http" : "https",
  136. cliParams.get(CLI_PARAM_HOST[0]),
  137. cliParams.get(CLI_PARAM_USERNAME[0]), cliParams.get(CLI_PARAM_PASSWORD[0]), httpPort));
  138. }
  139. else {
  140. cliParams.setHttpConfig(new NamePasswordConfiguration(
  141. cliParams.containsKey(CLI_PARAM_INSECURE[0]) ? "http" : "https",
  142. cliParams.get(CLI_PARAM_HOST[0]),
  143. cliParams.get(CLI_PARAM_USERNAME[0]), cliParams.get(CLI_PARAM_PASSWORD[0])));
  144. }
  145. if(cliParams.containsKey(CLI_PARAM_FTP_PORT[0])) {
  146. String ftpPortString = cliParams.get(CLI_PARAM_FTP_PORT[0]);
  147. int ftpPort = 0;
  148. try {
  149. ftpPort = Integer.parseInt(ftpPortString);
  150. }
  151. catch(NumberFormatException e) {
  152. throw new InvalidArgumentException("Invalid WebDav port value: '" + ftpPortString+"'.");
  153. }
  154. cliParams.setFtpConfig(new NamePasswordConfiguration(
  155. cliParams.containsKey(CLI_PARAM_INSECURE[0]) ? "http" : "https",
  156. cliParams.get(CLI_PARAM_FTP_HOST[0]),
  157. cliParams.get(CLI_PARAM_USERNAME[0]), cliParams.get(CLI_PARAM_PASSWORD[0]),ftpPort));
  158. }
  159. else {
  160. cliParams.setFtpConfig(new NamePasswordConfiguration(
  161. cliParams.containsKey(CLI_PARAM_INSECURE[0]) ? "http" : "https",
  162. cliParams.get(CLI_PARAM_FTP_HOST[0]),
  163. cliParams.get(CLI_PARAM_USERNAME[0]), cliParams.get(CLI_PARAM_PASSWORD[0])));
  164. }
  165. connectors = instantiateConnectors();
  166. String execute = cliParams.get(CLI_PARAM_EXECUTE[0]);
  167. String scripts = cliParams.get(CLI_PARAM_SCRIPT);
  168. if (execute != null && scripts != null && execute.length() > 0 && scripts.length() > 0) {
  169. throw new InvalidArgumentException("You can't execute a script and use the -e command line parameter at the same time.");
  170. }
  171. if (execute != null && execute.length() > 0) {
  172. l.debug("Executing arg=" + execute);
  173. execute(execute);
  174. }
  175. if (scripts != null && scripts.length() > 0) {
  176. String[] sas = scripts.split(",");
  177. for (String script : sas) {
  178. l.debug("Executing file=" + script);
  179. execute(new File(script));
  180. }
  181. }
  182. if (cliParams.containsKey(CLI_PARAM_HELP[0]))
  183. l.info(commandsHelp());
  184. finishedSucessfuly = true;
  185. } catch (InvalidArgumentException e) {
  186. l.error("Invalid or missing argument: " + e.getMessage());
  187. l.debug(e);
  188. Throwable c = e.getCause();
  189. while (c != null) {
  190. l.debug("Caused by: ", c);
  191. c = c.getCause();
  192. }
  193. HelpFormatter formatter = new HelpFormatter();
  194. formatter.printHelp("gooddata-cli [<options> ...] -H|--help|<script>|-e <command>", ops);
  195. finishedSucessfuly = false;
  196. } catch (InvalidCommandException e) {
  197. l.error("Invalid command: " + e.getMessage());
  198. l.debug(e);
  199. Throwable c = e.getCause();
  200. while (c != null) {
  201. l.debug("Caused by: ", c);
  202. c = c.getCause();
  203. }
  204. finishedSucessfuly = false;
  205. } catch (InvalidParameterException e) {
  206. l.error("Invalid command parameter: " + e.getMessage());
  207. l.debug(e);
  208. Throwable c = e.getCause();
  209. while (c != null) {
  210. l.debug("Caused by: ", c);
  211. c = c.getCause();
  212. }
  213. finishedSucessfuly = false;
  214. } catch (SfdcException e) {
  215. l.error("Error communicating with SalesForce: " + e.getMessage());
  216. l.debug(e);
  217. Throwable c = e.getCause();
  218. while (c != null) {
  219. l.debug("Caused by: ", c);
  220. c = c.getCause();
  221. }
  222. finishedSucessfuly = false;
  223. } catch (ProcessingException e) {
  224. l.error("Error processing command: " + e.getMessage());
  225. l.debug(e);
  226. Throwable c = e.getCause();
  227. while (c != null) {
  228. l.debug("Caused by: ", c);
  229. c = c.getCause();
  230. }
  231. finishedSucessfuly = false;
  232. } catch (ModelException e) {
  233. l.error("Model issue: " + e.getMessage());
  234. l.debug(e);
  235. Throwable c = e.getCause();
  236. while (c != null) {
  237. l.debug("Caused by: ", c);
  238. c = c.getCause();
  239. }
  240. finishedSucessfuly = false;
  241. } catch (IOException e) {
  242. l.error("Encountered an IO problem. Please check that all files that you use in your command line arguments and commands exist." + e.getMessage());
  243. l.debug(e);
  244. Throwable c = e.getCause();
  245. while (c != null) {
  246. l.debug("Caused by: ", c);
  247. c = c.getCause();
  248. }
  249. finishedSucessfuly = false;
  250. } catch (InternalErrorException e) {
  251. Throwable c = e.getCause();
  252. if (c != null && c instanceof SQLException) {
  253. l.error("Error extracting data. Can't process the incoming data. Please check the CSV file " +
  254. "separator and consistency (same number of columns in each row). Also, please make sure " +
  255. "that the number of columns in your XML config file matches the number of rows in your " +
  256. "data source. Make sure that your file is readable by other users (particularly the mysql user). " +
  257. "More info: ", c);
  258. } else {
  259. l.error("Internal error: " + e.getMessage());
  260. l.debug(e);
  261. c = e.getCause();
  262. while (c != null) {
  263. l.debug("Caused by: ", c);
  264. c = c.getCause();
  265. }
  266. }
  267. finishedSucessfuly = false;
  268. } catch (HttpMethodException e) {
  269. l.debug("Error executing GoodData REST API: " + e);
  270. Throwable c = e.getCause();
  271. while (c != null) {
  272. l.debug("Caused by: ", c);
  273. c = c.getCause();
  274. }
  275. String msg = e.getMessage();
  276. String requestId = e.getRequestId();
  277. if (requestId != null) {
  278. msg += "\n\n" +
  279. "If you believe this is not your fault, good people from support\n" +
  280. "portal (http://support.gooddata.com) may help you.\n\n" +
  281. "Show them this error ID: " + requestId;
  282. }
  283. if(msg.contains("503 Service Unavailable")) {
  284. l.error("GoodData platform is undergoing maintenance. For information regarding this outage:\n" +
  285. "Support Portal\n" +
  286. "(415) 200-0194");
  287. } else
  288. l.error(msg);
  289. finishedSucessfuly = false;
  290. } catch (GdcRestApiException e) {
  291. l.error("REST API invocation error: " + e.getMessage());
  292. l.debug(e, e);
  293. Throwable c = e.getCause();
  294. while (c != null) {
  295. if (c instanceof HttpMethodException) {
  296. HttpMethodException ex = (HttpMethodException) c;
  297. String msg = ex.getMessage();
  298. if (msg != null && msg.length() > 0 && msg.indexOf("/ldm/manage") > 0) {
  299. l.error("Error creating/updating logical data model (executing MAQL DDL).");
  300. if (msg.indexOf(".date") > 0) {
  301. l.error("Bad time dimension schemaReference.");
  302. } else {
  303. l.error("You are either trying to create a data object that already exists " +
  304. "(executing the same MAQL multiple times) or providing a wrong reference " +
  305. "or schemaReference in your XML configuration.");
  306. }
  307. }
  308. }
  309. l.debug("Caused by: ", c);
  310. c = c.getCause();
  311. }
  312. finishedSucessfuly = false;
  313. } catch (GdcException e) {
  314. l.error("Unrecognized error: " + e.getMessage());
  315. l.debug(e);
  316. Throwable c = e.getCause();
  317. while (c != null) {
  318. l.debug("Caused by: ", c);
  319. c = c.getCause();
  320. }
  321. finishedSucessfuly = false;
  322. } finally {
  323. /*
  324. if (cliParams != null)
  325. context.getRestApi(cliParams).logout();
  326. */
  327. }
  328. }
  329. /**
  330. * Parse and validate the cli arguments
  331. *
  332. * @param ln parsed command line
  333. * @return parsed cli parameters wrapped in the CliParams
  334. * @throws InvalidArgumentException in case of nonexistent or incorrect cli args
  335. */
  336. protected CliParams parse(CommandLine ln, Properties defaults) throws InvalidArgumentException {
  337. l.debug("Parsing cli " + ln);
  338. CliParams cp = new CliParams();
  339. for (Option o : Options) {
  340. String name = o.getLongOpt();
  341. if (ln.hasOption(name)) {
  342. cp.put(name, ln.getOptionValue(name));
  343. } else if (defaults.getProperty(name) != null) {
  344. cp.put(name, defaults.getProperty(name));
  345. }
  346. }
  347. if(cp.containsKey(CLI_PARAM_HTTP_PROXY_HOST[0])) {
  348. System.setProperty("http.proxyHost", cp.get(CLI_PARAM_HTTP_PROXY_HOST[0]));
  349. }
  350. if(cp.containsKey(CLI_PARAM_HTTP_PROXY_PORT[0])) {
  351. System.setProperty("http.proxyPort", cp.get(CLI_PARAM_HTTP_PROXY_PORT[0]));
  352. }
  353. if(cp.containsKey(CLI_PARAM_HTTP_PROXY_USERNAME[0])) {
  354. System.setProperty("http.proxyUser", cp.get(CLI_PARAM_HTTP_PROXY_USERNAME[0]));
  355. System.setProperty("http.proxyUserName", cp.get(CLI_PARAM_HTTP_PROXY_USERNAME[0]));
  356. System.setProperty("http.proxyUsername", cp.get(CLI_PARAM_HTTP_PROXY_USERNAME[0]));
  357. }
  358. if(cp.containsKey(CLI_PARAM_HTTP_PROXY_PASSWORD[0])) {
  359. System.setProperty("http.proxyPassword", cp.get(CLI_PARAM_HTTP_PROXY_PASSWORD[0]));
  360. }
  361. if (cp.containsKey(CLI_PARAM_VERSION[0])) {
  362. l.info("GoodData CL version 1.2.67" +
  363. ((BUILD_NUMBER.length() > 0) ? ", build " + BUILD_NUMBER : "."));
  364. System.exit(0);
  365. }
  366. // use default host if there is no host in the CLI params
  367. if (!cp.containsKey(CLI_PARAM_HOST[0])) {
  368. cp.put(CLI_PARAM_HOST[0], Defaults.DEFAULT_HOST);
  369. }
  370. l.debug("Using host " + cp.get(CLI_PARAM_HOST[0]));
  371. // create default FTP host if there is no host in the CLI params
  372. /*
  373. if (!cp.containsKey(CLI_PARAM_FTP_HOST[0])) {
  374. String[] hcs = cp.get(CLI_PARAM_HOST[0]).split("\\.");
  375. if (hcs != null && hcs.length > 0) {
  376. String ftpHost = "";
  377. for (int i = 0; i < hcs.length; i++) {
  378. if (i > 0)
  379. ftpHost += "." + hcs[i];
  380. else
  381. ftpHost = hcs[i] + N.FTP_SRV_SUFFIX;
  382. }
  383. cp.put(CLI_PARAM_FTP_HOST[0], ftpHost);
  384. } else {
  385. throw new InvalidArgumentException("Invalid format of the GoodData REST API host: " +
  386. cp.get(CLI_PARAM_HOST[0]));
  387. }
  388. }
  389. l.debug("Using FTP host " + cp.get(CLI_PARAM_FTP_HOST[0]));
  390. */
  391. // Default to secure protocol if there is no host in the CLI params
  392. // Assume insecure protocol if user specifies "HTTPS", for backwards compatibility
  393. if (cp.containsKey(CLI_PARAM_PROTO[0])) {
  394. String proto = ln.getOptionValue(CLI_PARAM_PROTO[0]).toLowerCase();
  395. if (!"http".equalsIgnoreCase(proto) && !"https".equalsIgnoreCase(proto)) {
  396. throw new InvalidArgumentException("Invalid '" + CLI_PARAM_PROTO[0] + "' parameter. Use HTTP or HTTPS.");
  397. }
  398. if ("http".equalsIgnoreCase(proto)) {
  399. cp.put(CLI_PARAM_INSECURE[0], "true");
  400. }
  401. }
  402. if (cp.containsKey(CLI_PARAM_INSECURE[0]))
  403. cp.put(CLI_PARAM_INSECURE[0], "true");
  404. l.debug("Using " + (cp.containsKey(CLI_PARAM_INSECURE[0]) ? "in" : "") + "secure protocols");
  405. if (ln.getArgs().length == 0 && !ln.hasOption(CLI_PARAM_EXECUTE[0]) && !ln.hasOption(CLI_PARAM_HELP[0])) {
  406. throw new InvalidArgumentException("No command has been given, quitting.");
  407. }
  408. String scripts = "";
  409. for (final String arg : ln.getArgs()) {
  410. if (scripts.length() > 0)
  411. scripts += "," + arg;
  412. else
  413. scripts += arg;
  414. }
  415. cp.put(CLI_PARAM_SCRIPT, scripts);
  416. return cp;
  417. }
  418. /**
  419. * Executes the commands in String
  420. *
  421. * @param commandsStr commands string
  422. */
  423. public void execute(final String commandsStr) {
  424. List<Command> cmds = new ArrayList<Command>();
  425. cmds.addAll(parseCmd(commandsStr));
  426. for (Command command : cmds) {
  427. boolean processed = false;
  428. for (int i = 0; i < connectors.length && !processed; i++) {
  429. processed = connectors[i].processCommand(command, cliParams, context);
  430. }
  431. if (!processed)
  432. this.processCommand(command, cliParams, context);
  433. }
  434. }
  435. /**
  436. * Executes the commands in file
  437. *
  438. * @param scriptFile file with commands
  439. * @throws IOException in case of an IO issue
  440. */
  441. public void execute(final File scriptFile) throws IOException {
  442. List<Command> cmds = new ArrayList<Command>();
  443. cmds.addAll(parseCmd(FileUtil.readStringFromFile(scriptFile.getAbsolutePath())));
  444. for (Command command : cmds) {
  445. boolean processed = false;
  446. for (int i = 0; i < connectors.length && !processed; i++) {
  447. processed = connectors[i].processCommand(command, cliParams, context);
  448. }
  449. if (!processed)
  450. processed = this.processCommand(command, cliParams, context);
  451. if (!processed)
  452. throw new InvalidCommandException("Unknown command '" + command.getCommand() + "'");
  453. }
  454. }
  455. /**
  456. * Returns the help for commands
  457. *
  458. * @return help text
  459. */
  460. public static String commandsHelp() {
  461. try {
  462. final InputStream is = CliParams.class.getResourceAsStream("/com/gooddata/processor/COMMANDS.txt");
  463. if (is == null)
  464. throw new IOException();
  465. return FileUtil.readStringFromStream(is);
  466. } catch (IOException e) {
  467. l.error("Could not read com/gooddata/processor/COMMANDS.txt");
  468. }
  469. return "";
  470. }
  471. private static boolean checkJavaVersion() {
  472. String version = System.getProperty("java.version");
  473. if (version.startsWith("1.8") || version.startsWith("1.7") || version.startsWith("1.6") || version.startsWith("1.5"))
  474. return true;
  475. l.error("You're running Java " + version + ". Please use Java 1.5 or higher for running this tool. " +
  476. "Please refer to http://java.sun.com/javase/downloads/index.jsp for a more recent Java version.");
  477. throw new InternalErrorException("You're running Java " + version + ". Please use use Java 1.5 or higher for running this tool. " +
  478. "Please refer to http://java.sun.com/javase/downloads/index.jsp for a more recent Java version.");
  479. }
  480. /**
  481. * The main CLI processor
  482. *
  483. * @param args command line argument
  484. */
  485. public static void main(String[] args) {
  486. checkJavaVersion();
  487. Properties defaults = loadDefaults();
  488. for (Option o : Options)
  489. ops.addOption(o);
  490. try {
  491. CommandLineParser parser = new GnuParser();
  492. CommandLine cmdline = parser.parse(ops, args);
  493. GdcDI gdi = new GdcDI(cmdline, defaults);
  494. if (!gdi.finishedSucessfuly) {
  495. System.exit(1);
  496. }
  497. } catch (org.apache.commons.cli.ParseException e) {
  498. l.error("Error parsing command line parameters: ", e);
  499. l.debug("Error parsing command line parameters", e);
  500. }
  501. }
  502. private void setupHttpProxies() {
  503. //CredentialsProvider proxyCredentials = new BasicCredentialsProvider ();
  504. }
  505. /**
  506. * Parses the commands
  507. *
  508. * @param cmd commands string
  509. * @return array of commands
  510. * @throws InvalidCommandException in case there is an invalid command
  511. */
  512. protected static List<Command> parseCmd(String cmd) throws InvalidCommandException {
  513. l.debug("Parsing comands: " + cmd);
  514. try {
  515. if (cmd != null && cmd.length() > 0) {
  516. Reader r = new StringReader(cmd);
  517. DIScriptParser parser = new DIScriptParser(r);
  518. List<Command> commands = parser.parse();
  519. l.debug("Running " + commands.size() + " commands.");
  520. for (Command c : commands) {
  521. l.debug("Command=" + c.getCommand() + " params=" + c.getParameters());
  522. }
  523. return commands;
  524. }
  525. } catch (ParseException e) {
  526. throw new InvalidCommandException("Can't parse command '" + cmd + "'");
  527. }
  528. throw new InvalidCommandException("Can't parse command (empty command).");
  529. }
  530. /**
  531. * {@inheritDoc}
  532. */
  533. public boolean processCommand(Command c, CliParams cli, ProcessingContext ctx) throws ProcessingException {
  534. l.debug("Processing command " + c.getCommand());
  535. try {
  536. // take project id from command line, may be override in the script
  537. if (cliParams.get(CLI_PARAM_PROJECT[0]) != null) {
  538. ctx.setProjectId(cliParams.get(CLI_PARAM_PROJECT[0]));
  539. }
  540. if (c.match("CreateProject")) {
  541. createProject(c, cli, ctx);
  542. } else if (c.match("DropProject") || c.match("DeleteProject")) {
  543. dropProject(c, cli, ctx);
  544. } else if (c.match("OpenProject")) {
  545. ctx.setProjectId(c.getParamMandatory("id"));
  546. c.paramsProcessed();
  547. l.debug("Opened project id=" + ctx.getProjectId());
  548. l.info("Opened project id=" + ctx.getProjectId());
  549. } else if (c.match("StoreProject") || c.match("RememberProject")) {
  550. storeProject(c, cli, ctx);
  551. } else if (c.match("ExecuteDml")) {
  552. executeDML(c, cli, ctx);
  553. } else if (c.match("RetrieveProject") || c.match("UseProject")) {
  554. retrieveProject(c, cli, ctx);
  555. } else if (c.match("ExportProject")) {
  556. exportProject(c, cli, ctx);
  557. } else if (c.match("ImportProject")) {
  558. importProject(c, cli, ctx);
  559. } else if (c.match("Lock")) {
  560. lock(c, cli, ctx);
  561. } else if (c.match("GetReports")) {
  562. getReports(c, cli, ctx);
  563. } else if (c.match("CreateUser")) {
  564. createUser(c, cli, ctx);
  565. } else if (c.match("AddUsersToProject")) {
  566. addUsersToProject(c, cli, ctx);
  567. } else if (c.match("DisableUsersInProject")) {
  568. disableUsersInProject(c, cli, ctx);
  569. } else if (c.match("GetProjectUsers")) {
  570. getProjectUsers(c, cli, ctx);
  571. } else if (c.match("InviteUser")) {
  572. inviteUser(c, cli, ctx);
  573. } else if (c.match("ExecuteReports")) {
  574. executeReports(c, cli, ctx);
  575. } else if (c.match("StoreMetadataObject")) {
  576. storeMdObject(c, cli, ctx);
  577. } else if (c.match("DropMetadataObject")) {
  578. dropMdObject(c, cli, ctx);
  579. } else if (c.match("RetrieveMetadataObject")) {
  580. getMdObject(c, cli, ctx);
  581. } else if (c.match("ExportMetadataObjects")) {
  582. exportMDObject(c, cli, ctx);
  583. } else if (c.match("ImportMetadataObjects")) {
  584. importMDObject(c, cli, ctx);
  585. } else if (c.match("ExportJdbcToCsv")) {
  586. exportJdbcToCsv(c, cli, ctx);
  587. } else if (c.match("MigrateDatasets")) {
  588. migrateDatasets(c, cli, ctx);
  589. } else if (c.match("GenerateManifests")) {
  590. generateManifests(c, cli, ctx);
  591. } else {
  592. l.debug("No match command " + c.getCommand());
  593. return false;
  594. }
  595. } catch (IOException e) {
  596. l.debug("Processing command " + c.getCommand() + " failed", e);
  597. throw new ProcessingException(e);
  598. } catch (InterruptedException e) {
  599. l.debug("Processing command " + c.getCommand() + " failed", e);
  600. throw new ProcessingException(e);
  601. }
  602. l.debug("Command processing " + c.getCommand() + " finished.");
  603. return true;
  604. }
  605. /**
  606. * Executes MAQL DML
  607. *
  608. * @param c command
  609. * @param p cli parameters
  610. * @param ctx current context
  611. * @throws IOException IO issues
  612. */
  613. private void executeDML(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  614. try {
  615. l.debug("Executing MAQL DML.");
  616. String pid = ctx.getProjectIdMandatory();
  617. final String cmd = c.getParamMandatory("maql");
  618. c.paramsProcessed();
  619. String taskUri = ctx.getRestApi(p).executeDML(pid, cmd);
  620. if (taskUri != null && taskUri.length() > 0) {
  621. l.debug("Checking MAQL DML execution status.");
  622. String status = "";
  623. while (!"OK".equalsIgnoreCase(status) && !"ERROR".equalsIgnoreCase(status) && !"WARNING".equalsIgnoreCase(status)) {
  624. status = ctx.getRestApi(p).getMigrationStatus(taskUri);
  625. l.debug("MAQL DML execution status = " + status);
  626. Thread.sleep(Constants.POLL_INTERVAL);
  627. }
  628. l.info("MAQL DML execution finished with status " + status);
  629. if ("ERROR".equalsIgnoreCase(status)) {
  630. l.error("Error executing the MAQL DML. Check debug log for more details.");
  631. throw new GdcRestApiException("Error executing the MAQL DML. Check debug log for more details.");
  632. }
  633. } else {
  634. l.error("MAQL DML execution hasn't returned any task URI.");
  635. throw new InternalErrorException("MAQL DML execution hasn't returned any task URI.");
  636. }
  637. l.debug("Finished MAQL DML execution.");
  638. l.info("MAQL DML command '" + cmd + "' successfully executed.");
  639. } catch (InterruptedException e) {
  640. throw new InternalErrorException(e);
  641. }
  642. }
  643. /**
  644. * Exports project
  645. *
  646. * @param c command
  647. * @param p cli parameters
  648. * @param ctx current context
  649. * @throws IOException IO issues
  650. */
  651. private void exportProject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  652. try {
  653. l.info("Exporting project.");
  654. String pid = ctx.getProjectIdMandatory();
  655. final String eu = c.getParamMandatory("exportUsers");
  656. final boolean exportUsers = (eu != null && "true".equalsIgnoreCase(eu));
  657. final String ed = c.getParamMandatory("exportData");
  658. final boolean exportData = (ed != null && "true".equalsIgnoreCase(ed));
  659. final String fileName = c.getParamMandatory("tokenFile");
  660. String au = c.getParam("authorizedUsers");
  661. c.paramsProcessed();
  662. String[] authorizedUsers = null;
  663. if (au != null && au.length() > 0) {
  664. authorizedUsers = au.split(",");
  665. }
  666. GdcRESTApiWrapper.ProjectExportResult r = ctx.getRestApi(p).exportProject(pid, exportUsers, exportData,
  667. authorizedUsers);
  668. String taskUri = r.getTaskUri();
  669. String token = r.getExportToken();
  670. if (taskUri != null && taskUri.length() > 0) {
  671. l.debug("Checking project export status.");
  672. String status = "";
  673. while (!"OK".equalsIgnoreCase(status) && !"ERROR".equalsIgnoreCase(status) && !"WARNING".equalsIgnoreCase(status)) {
  674. status = ctx.getRestApi(p).getMigrationStatus(taskUri);
  675. l.debug("Project export status = " + status);
  676. Thread.sleep(Constants.POLL_INTERVAL);
  677. }
  678. l.info("Project export finished with status " + status);
  679. if ("OK".equalsIgnoreCase(status) || "WARNING".equalsIgnoreCase(status)) {
  680. FileUtil.writeStringToFile(token, fileName);
  681. } else {
  682. l.error("Error exporting project. Check debug log for more details.");
  683. throw new GdcRestApiException("Error exporting project. Check debug log for more details.");
  684. }
  685. } else {
  686. l.error("Project export hasn't returned any task URI.");
  687. throw new InternalErrorException("Project export hasn't returned any task URI.");
  688. }
  689. l.debug("Finished project export.");
  690. l.info("Project " + pid + " successfully exported. Import token is " + token);
  691. } catch (InterruptedException e) {
  692. throw new InternalErrorException(e);
  693. }
  694. }
  695. /**
  696. * Imports project
  697. *
  698. * @param c command
  699. * @param p cli parameters
  700. * @param ctx current context
  701. * @throws IOException IO issues
  702. */
  703. private void importProject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  704. try {
  705. l.info("Importing project.");
  706. String pid = ctx.getProjectIdMandatory();
  707. final String tokenFile = c.getParamMandatory("tokenFile");
  708. c.paramsProcessed();
  709. String token = FileUtil.readStringFromFile(tokenFile).trim();
  710. String taskUri = ctx.getRestApi(p).importProject(pid, token);
  711. if (taskUri != null && taskUri.length() > 0) {
  712. l.debug("Checking project import status.");
  713. String status = "";
  714. while (!"OK".equalsIgnoreCase(status) && !"ERROR".equalsIgnoreCase(status) && !"WARNING".equalsIgnoreCase(status)) {
  715. status = ctx.getRestApi(p).getMigrationStatus(taskUri);
  716. l.debug("Project import status = " + status);
  717. Thread.sleep(Constants.POLL_INTERVAL);
  718. }
  719. l.info("Project import finished with status " + status);
  720. if ("ERROR".equalsIgnoreCase(status)) {
  721. l.error("Error importing project. Check debug log for more details.");
  722. throw new GdcRestApiException("Error importing project. Check debug log for more details.");
  723. }
  724. } else {
  725. l.error("Project import hasn't returned any task URI.");
  726. throw new InternalErrorException("Project import hasn't returned any task URI.");
  727. }
  728. l.debug("Finished project import.");
  729. l.info("Project " + pid + " successfully imported.");
  730. } catch (InterruptedException e) {
  731. throw new InternalErrorException(e);
  732. }
  733. }
  734. /**
  735. * Exports MD objects
  736. *
  737. * @param c command
  738. * @param p cli parameters
  739. * @param ctx current context
  740. * @throws IOException IO issues
  741. */
  742. private void exportMDObject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  743. try {
  744. l.info("Exporting metadata objects.");
  745. String token;
  746. String pid = ctx.getProjectIdMandatory();
  747. final String fileName = c.getParamMandatory("tokenFile");
  748. final String idscs = c.getParamMandatory("objectIDs");
  749. c.paramsProcessed();
  750. if (idscs != null && idscs.length() > 0) {
  751. String[] idss = idscs.split(",");
  752. List<Integer> ids = new ArrayList<Integer>();
  753. for (String id : idss) {
  754. try {
  755. ids.add(Integer.parseInt(id));
  756. } catch (NumberFormatException e) {
  757. l.debug("Invalid metadata object ID " + id, e);
  758. l.error("Invalid metadata object ID " + id);
  759. throw new InvalidParameterException("Invalid metadata object ID " + id, e);
  760. }
  761. }
  762. GdcRESTApiWrapper.ProjectExportResult r = ctx.getRestApi(p).exportMD(pid, ids);
  763. String taskUri = r.getTaskUri();
  764. token = r.getExportToken();
  765. if (taskUri != null && taskUri.length() > 0) {
  766. l.debug("Checking MD export status.");
  767. String status = "";
  768. while (!"OK".equalsIgnoreCase(status) && !"ERROR".equalsIgnoreCase(status) && !"WARNING".equalsIgnoreCase(status)) {
  769. status = ctx.getRestApi(p).getTaskManStatus(taskUri);
  770. l.debug("MD export status = " + status);
  771. Thread.sleep(Constants.POLL_INTERVAL);
  772. }
  773. l.info("MD export finished with status " + status);
  774. if ("OK".equalsIgnoreCase(status) || "WARNING".equalsIgnoreCase(status)) {
  775. FileUtil.writeStringToFile(token, fileName);
  776. } else {
  777. l.error("Error exporting metadata. Check debug log for more details.");
  778. throw new GdcRestApiException("Error exporting metadata. Check debug log for more details.");
  779. }
  780. } else {
  781. l.error("MD export hasn't returned any task URI.");
  782. throw new InternalErrorException("MD export hasn't returned any task URI.");
  783. }
  784. } else {
  785. l.debug("The objectIDs parameter must contain a comma separated list of metadata object IDs!");
  786. l.error("The objectIDs parameter must contain a comma separated list of metadata object IDs!");
  787. throw new InvalidParameterException("The objectIDs parameter must contain a comma separated list of metadata object IDs!");
  788. }
  789. l.debug("Finished MD export.");
  790. l.info("Project " + pid + " metadata successfully exported. Import token is " + token);
  791. } catch (InterruptedException e) {
  792. throw new InternalErrorException(e);
  793. }
  794. }
  795. /**
  796. * Imports MD objects
  797. *
  798. * @param c command
  799. * @param p cli parameters
  800. * @param ctx current context
  801. * @throws IOException IO issues
  802. */
  803. private void importMDObject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  804. try {
  805. l.info("Importing metadata objects.");
  806. String pid = ctx.getProjectIdMandatory();
  807. final String tokenFile = c.getParamMandatory("tokenFile");
  808. String token = FileUtil.readStringFromFile(tokenFile).trim();
  809. /*
  810. Currently not supported
  811. final String ov = c.getParam("overwrite");
  812. final boolean overwrite = (ov != null && "true".equalsIgnoreCase(ov));
  813. */
  814. final String ul = c.getParam("updateLDM");
  815. final boolean updateLDM = (ul != null && "true".equalsIgnoreCase(ul));
  816. final boolean overwrite = true;
  817. c.paramsProcessed();
  818. String taskUri = ctx.getRestApi(p).importMD(pid, token, overwrite, updateLDM);
  819. if (taskUri != null && taskUri.length() > 0) {
  820. l.debug("Checking MD import status.");
  821. String status = "";
  822. while (!"OK".equalsIgnoreCase(status) && !"ERROR".equalsIgnoreCase(status) && !"WARNING".equalsIgnoreCase(status)) {
  823. status = ctx.getRestApi(p).getTaskManStatus(taskUri);
  824. l.debug("MD import status = " + status);
  825. Thread.sleep(Constants.POLL_INTERVAL);
  826. }
  827. l.info("MD import finished with status " + status);
  828. if ("ERROR".equalsIgnoreCase(status)) {
  829. l.error("Error importing MD. Check debug log for more details.");
  830. throw new GdcRestApiException("Error importing MD. Check debug log for more details.");
  831. }
  832. } else {
  833. l.error("MD import hasn't returned any task URI.");
  834. throw new InternalErrorException("MD import hasn't returned any task URI.");
  835. }
  836. l.debug("Finished metadata import.");
  837. l.info("Project " + pid + " metadata successfully imported.");
  838. } catch (InterruptedException e) {
  839. throw new InternalErrorException(e);
  840. }
  841. }
  842. /**
  843. * Creates a new user
  844. *
  845. * @param c command
  846. * @param p cli parameters
  847. * @param ctx current context
  848. * @throws IOException IO issues
  849. */
  850. private void createUser(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  851. l.info("Creating new user.");
  852. String domain = c.getParamMandatory("domain");
  853. GdcRESTApiWrapper.GdcUser user = new GdcRESTApiWrapper.GdcUser();
  854. user.setLogin(c.getParamMandatory("username"));
  855. user.setPassword(c.getParamMandatory("password"));
  856. user.setVerifyPassword(user.getPassword());
  857. user.setFirstName(c.getParamMandatory("firstName"));
  858. user.setLastName(c.getParamMandatory("lastName"));
  859. user.setCompanyName(c.getParam("company"));
  860. user.setPosition(c.getParam("position"));
  861. user.setCountry(c.getParam("country"));
  862. user.setPhoneNumber(c.getParam("phone"));
  863. user.setSsoProvider(c.getParam("ssoProvider"));
  864. user.setEmail(c.getParam("email"));
  865. String usersFile = c.getParam("usersFile");
  866. String appnd = c.getParam("append");
  867. c.paramsProcessed();
  868. final boolean append = (appnd != null && "true".equalsIgnoreCase(appnd));
  869. String r = ctx.getRestApi(p).createUser(domain, user);
  870. if (r != null && r.length() > 0 && usersFile != null && usersFile.length() > 0) {
  871. FileUtil.writeStringToFile(r + "\n", usersFile, append);
  872. }
  873. l.info("User " + user.getLogin() + "' successfully created. User URI: " + r);
  874. }
  875. /**
  876. * Adds a new user to project
  877. *
  878. * @param c command
  879. * @param p cli parameters
  880. * @param ctx current context
  881. * @throws IOException IO issues
  882. */
  883. private void addUsersToProject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  884. l.info("Adding users to project.");
  885. String pid = ctx.getProjectIdMandatory();
  886. String usersFile = c.getParamMandatory("usersFile");
  887. List<String> uris = new ArrayList<String>();
  888. BufferedReader r = FileUtil.createBufferedUtf8Reader(usersFile);
  889. String uri = r.readLine();
  890. while (uri != null && uri.trim().length() > 0) {
  891. uris.add(uri.trim());
  892. uri = r.readLine();
  893. }
  894. String role = c.getParam("role");
  895. c.paramsProcessed();
  896. ctx.getRestApi(p).addUsersToProject(pid, uris, role);
  897. l.info("Users " + uris + "' successfully added to project " + pid);
  898. }
  899. /**
  900. * Adds a new user to project
  901. *
  902. * @param c command
  903. * @param p cli parameters
  904. * @param ctx current context
  905. * @throws IOException IO issues
  906. */
  907. private void disableUsersInProject(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  908. l.info("Disabling users in project.");
  909. String pid = ctx.getProjectIdMandatory();
  910. String usersFile = c.getParamMandatory("usersFile");
  911. c.paramsProcessed();
  912. List<String> uris = new ArrayList<String>();
  913. BufferedReader r = FileUtil.createBufferedUtf8Reader(usersFile);
  914. String uri = r.readLine();
  915. while (uri != null && uri.trim().length() > 0) {
  916. uris.add(uri.trim());
  917. uri = r.readLine();
  918. }
  919. ctx.getRestApi(p).disableUsersInProject(pid, uris);
  920. l.info("Users " + uris + "' successfully disabled in project " + pid);
  921. }
  922. /**
  923. * Adds a new user to project
  924. *
  925. * @param c command
  926. * @param p cli parameters
  927. * @param ctx current context
  928. * @throws IOException IO issues
  929. */
  930. private void getProjectUsers(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  931. String pid = ctx.getProjectIdMandatory();
  932. l.info("Getting users from project " + pid);
  933. String usersFile = c.getParamMandatory("usersFile");
  934. String field = c.getParamMandatory("field");
  935. String activeOnlys = c.getParam("activeOnly");
  936. c.paramsProcessed();
  937. final boolean activeOnly = (activeOnlys != null && "true".equalsIgnoreCase(activeOnlys));
  938. if ("email".equalsIgnoreCase(field) || "uri".equalsIgnoreCase(field)) {
  939. List<GdcRESTApiWrapper.GdcUser> users = ctx.getRestApi(p).getProjectUsers(pid, activeOnly);
  940. for (GdcRESTApiWrapper.GdcUser user : users) {
  941. if ("email".equalsIgnoreCase(field)) {
  942. FileUtil.writeStringToFile(user.getLogin() + "\n", usersFile, true);
  943. }
  944. if ("uri".equalsIgnoreCase(field)) {
  945. FileUtil.writeStringToFile(user.getUri() + "\n", usersFile, true);
  946. }
  947. l.info("User " + user.getLogin() + "' successfully added. User URI: " + user.getUri());
  948. }
  949. } else {
  950. l.error("Invalid field parameter. Only values 'email' and 'uri' are currently supported.");
  951. }
  952. }
  953. /**
  954. * Create new project command processor
  955. *
  956. * @param c command
  957. * @param p cli parameters
  958. * @param ctx current context
  959. */
  960. private void createProject(Command c, CliParams p, ProcessingContext ctx) {
  961. try {
  962. String name = c.getParamMandatory("name");
  963. String desc = c.getParam("desc");
  964. String pTempUri = c.getParam("templateUri");
  965. String driver = c.getParam("driver");
  966. String token = null;
  967. String[] tokens = new String[] { c.getParam("authorizationToken"),
  968. c.getParam("accessToken"), p.get(CLI_PARAM_AUTHORIZATION_TOKEN[0]),
  969. System.getenv("AUTHORIZATION_TOKEN")
  970. };
  971. for (final String t : tokens) {
  972. if (t != null && t.length() > 0) {
  973. token = t;
  974. break;
  975. }
  976. }
  977. if (token == null) {
  978. throw new InvalidParameterException("The 'authorizationToken' parameter to the CreateProject " +
  979. "call is mandatory. Please specify it via the 'authorizationToken' parameter of the " +
  980. "CreateProject call or via the -a commandline parameter or the AUTHORIZATION_TOKEN " +
  981. "env variable.");
  982. }
  983. c.paramsProcessed();
  984. if (desc == null || desc.length() <= 0)
  985. desc = name;
  986. ctx.setProjectId(ctx.getRestApi(p).createProject(StringUtil.toTitle(name), StringUtil.toTitle(desc), pTempUri, driver, token));
  987. String pid = ctx.getProjectIdMandatory();
  988. checkProjectCreationStatus(pid, p, ctx);
  989. l.info("Project id = '" + pid + "' created.");
  990. } catch (InterruptedException e) {
  991. throw new InternalErrorException(e);
  992. }
  993. }
  994. /**
  995. * Exports all DB tables to CSV
  996. *
  997. * @param c command
  998. * @param p cli parameters
  999. * @param ctx current context
  1000. */
  1001. private void exportJdbcToCsv(Command c, CliParams p, ProcessingContext ctx) throws IOException {
  1002. try {
  1003. String usr = null;
  1004. if (c.checkParam("username"))
  1005. usr = c.getParam("username");
  1006. String psw = null;
  1007. if (c.checkParam("password"))
  1008. psw = c.getParam("password");
  1009. String drv = c.getParamMandatory("driver");
  1010. String url = c.getParamMandatory("url");
  1011. String fl = c.getParamMandatory("dir");
  1012. c.paramsProcessed();
  1013. File dir = new File(fl);
  1014. if (!dir.exists() || !dir.isDirectory()) {
  1015. throw new InvalidParameterException("The dir parameter in the ExportJdbcToCsv command must be an existing directory.");
  1016. }
  1017. DatabaseToCsv d = new DatabaseToCsv(drv, url, usr, psw);
  1018. d.export(dir.getAbsolutePath());
  1019. l.info("All tables successfully exported to " + dir.getAbs

Large files files are truncated, but you can click here to view the full file