/src/main/java/org/apache/ibatis/migration/CommandLine.java

http://mybatis.googlecode.com/ · Java · 231 lines · 213 code · 18 blank · 0 comment · 63 complexity · 068b71692cd74551b5151b525e54e6d9 MD5 · raw file

  1. package org.apache.ibatis.migration;
  2. import java.io.File;
  3. import java.io.PrintStream;
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.Date;
  7. import java.util.HashSet;
  8. import java.util.Set;
  9. import org.apache.ibatis.migration.commands.BootstrapCommand;
  10. import org.apache.ibatis.migration.commands.DownCommand;
  11. import org.apache.ibatis.migration.commands.InitializeCommand;
  12. import org.apache.ibatis.migration.commands.NewCommand;
  13. import org.apache.ibatis.migration.commands.PendingCommand;
  14. import org.apache.ibatis.migration.commands.ScriptCommand;
  15. import org.apache.ibatis.migration.commands.StatusCommand;
  16. import org.apache.ibatis.migration.commands.UpCommand;
  17. import org.apache.ibatis.migration.commands.VersionCommand;
  18. public class CommandLine {
  19. private static final String PATH_PREFIX = "--path=";
  20. private static final String ENV_PREFIX = "--env=";
  21. private static final String FORCE = "--force";
  22. private static final String TRACE = "--trace";
  23. private static final String HELP = "--help";
  24. private static final String TEMPLATE_PREFIX = "--template=";
  25. private static final String INIT = "init";
  26. private static final String BOOTSTRAP = "bootstrap";
  27. private static final String NEW = "new";
  28. private static final String UP = "up";
  29. private static final String DOWN = "down";
  30. private static final String PENDING = "pending";
  31. private static final String SCRIPT = "script";
  32. private static final String VERSION = "version";
  33. private static final String STATUS = "status";
  34. private static final Set<String> KNOWN_COMMANDS = Collections.unmodifiableSet(
  35. new HashSet<String>(Arrays.asList(INIT, NEW, UP, VERSION, DOWN, PENDING, STATUS, BOOTSTRAP, SCRIPT)));
  36. private PrintStream printStream;
  37. private File repository;
  38. private String environment;
  39. private String template;
  40. private boolean force;
  41. private boolean trace;
  42. private String command;
  43. private String params;
  44. private String parseError;
  45. private boolean help;
  46. public CommandLine(String[] args) {
  47. this.printStream = System.out;
  48. parse(args);
  49. validate();
  50. }
  51. public void setPrintStream(PrintStream out) {
  52. this.printStream = out;
  53. }
  54. public PrintStream getPrintStream() {
  55. return this.printStream;
  56. }
  57. public void execute() {
  58. boolean error = false;
  59. try {
  60. if (help) {
  61. printUsage();
  62. } else if (parseError != null) {
  63. error = true;
  64. printError();
  65. printUsage();
  66. } else {
  67. try {
  68. runCommand();
  69. } catch (Exception e) {
  70. error = true;
  71. printStream.println("\nERROR: " + e.getMessage());
  72. if (trace) {
  73. e.printStackTrace();
  74. }
  75. }
  76. }
  77. } finally {
  78. printStream.flush();
  79. if (error) {
  80. System.exit(1);
  81. }
  82. }
  83. }
  84. private void runCommand() {
  85. printStream.println("------------------------------------------------------------------------");
  86. printStream.printf("MyBatis Migrations - %s%n", command);
  87. printStream.println("------------------------------------------------------------------------");
  88. long start = System.currentTimeMillis();
  89. int exit = 0;
  90. try {
  91. if (INIT.equals(command)) {
  92. new InitializeCommand(repository, environment, force).execute(params);
  93. } else if (BOOTSTRAP.equals(command)) {
  94. new BootstrapCommand(repository, environment, force).execute(params);
  95. } else if (NEW.equals(command)) {
  96. new NewCommand(repository, environment, template, force).execute(params);
  97. } else if (STATUS.equals(command)) {
  98. new StatusCommand(repository, environment, force).execute(params);
  99. } else if (UP.equals(command)) {
  100. new UpCommand(repository, environment, force).execute(params);
  101. } else if (VERSION.equals(command)) {
  102. new VersionCommand(repository, environment, force).execute(params);
  103. } else if (PENDING.equals(command)) {
  104. new PendingCommand(repository, environment, force).execute(params);
  105. } else if (DOWN.equals(command)) {
  106. new DownCommand(repository, environment, force).execute(params);
  107. } else if (SCRIPT.equals(command)) {
  108. new ScriptCommand(repository, environment, force).execute(params);
  109. } else {
  110. String match = null;
  111. for (String knownCommand : KNOWN_COMMANDS) {
  112. if (knownCommand.startsWith(command)) {
  113. if (match != null) {
  114. throw new MigrationException("Ambiguous command shortcut: " + command);
  115. }
  116. match = knownCommand;
  117. }
  118. }
  119. if (match != null) {
  120. command = match;
  121. runCommand();
  122. } else {
  123. throw new MigrationException("Attempt to execute unknown command: " + command);
  124. }
  125. }
  126. } catch (Throwable t) {
  127. exit = -1;
  128. t.printStackTrace(printStream);
  129. } finally {
  130. printStream.println("------------------------------------------------------------------------");
  131. printStream.printf("MyBatis Migrations %s%n", (exit < 0) ? "FAILURE" : "SUCCESS");
  132. printStream.printf("Total time: %ss%n", ((System.currentTimeMillis() - start) / 1000));
  133. printStream.printf("Finished at: %s%n", new Date());
  134. final Runtime runtime = Runtime.getRuntime();
  135. final int megaUnit = 1024 * 1024;
  136. printStream.printf("Final Memory: %sM/%sM%n",
  137. (runtime.totalMemory() - runtime.freeMemory()) / megaUnit,
  138. runtime.totalMemory() / megaUnit);
  139. printStream.println("------------------------------------------------------------------------");
  140. System.exit(exit);
  141. }
  142. }
  143. private void parse(String[] args) {
  144. for (String arg : args) {
  145. if (arg.startsWith(PATH_PREFIX) && arg.length() > PATH_PREFIX.length()) {
  146. repository = new File(arg.split("=")[1]);
  147. } else if (arg.startsWith(ENV_PREFIX) && arg.length() > ENV_PREFIX.length()) {
  148. environment = arg.split("=")[1];
  149. } else if (arg.startsWith(TEMPLATE_PREFIX) && arg.length() > TEMPLATE_PREFIX.length()) {
  150. template = arg.split("=")[1];
  151. } else if (arg.startsWith(TRACE)) {
  152. trace = true;
  153. } else if (arg.startsWith(FORCE)) {
  154. force = true;
  155. } else if (arg.startsWith(HELP)) {
  156. help = true;
  157. } else if (command == null) {
  158. command = arg;
  159. } else if (params == null) {
  160. params = arg;
  161. } else {
  162. params += " ";
  163. params += arg;
  164. }
  165. }
  166. }
  167. private void validate() {
  168. if (repository == null) {
  169. repository = new File("./");
  170. }
  171. if (environment == null) {
  172. environment = "development";
  173. }
  174. if (repository.exists() && !repository.isDirectory()) {
  175. parseError = ("Migrations path must be a directory: " + repository.getAbsolutePath());
  176. } else {
  177. repository = new File(repository.getAbsolutePath());
  178. if (command == null) {
  179. parseError = "No command specified.";
  180. }
  181. }
  182. }
  183. private void printError() {
  184. printStream.println(parseError);
  185. printStream.flush();
  186. }
  187. private void printUsage() {
  188. printStream.println();
  189. printStream.println("Usage: migrate command [parameter] [--path=<directory>] [--env=<environment>] [--template=<path to custom template>]");
  190. printStream.println();
  191. printStream.println("--path=<directory> Path to repository. Default current working directory.");
  192. printStream.println("--env=<environment> Environment to configure. Default environment is 'development'.");
  193. printStream.println("--template=<template> Path to custom template for creating new sql scripts.");
  194. printStream.println("--force Forces script to continue even if SQL errors are encountered.");
  195. printStream.println("--help Displays this usage message.");
  196. printStream.println("--trace Shows additional error details (if any).");
  197. printStream.println();
  198. printStream.println("Commands:");
  199. printStream.println(" init Creates (if necessary) and initializes a migration path.");
  200. printStream.println(" bootstrap Runs the bootstrap SQL script (see scripts/bootstrap.sql for more).");
  201. printStream.println(" new <description> Creates a new migration with the provided description.");
  202. printStream.println(" up [n] Run unapplied migrations, ALL by default, or 'n' specified.");
  203. printStream.println(" down [n] Undoes migrations applied to the database. ONE by default or 'n' specified.");
  204. printStream.println(" version <version> Migrates the database up or down to the specified version.");
  205. printStream.println(" pending Force executes pending migrations out of order (not recommended).");
  206. printStream.println(" status Prints the changelog from the database if the changelog table exists.");
  207. printStream.println(" script <v1> <v2> Generates a delta migration script from version v1 to v2 (undo if v1 > v2).");
  208. printStream.println("");
  209. printStream.println(" * Shortcuts are accepted by using the first few (unambiguous) letters of each command..");
  210. printStream.println();
  211. printStream.flush();
  212. }
  213. }