1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.migration;
17
18 import static org.apache.ibatis.migration.options.OptionsParser.parse;
19
20 import java.io.File;
21 import java.io.PrintStream;
22 import java.util.Date;
23
24 import org.apache.ibatis.migration.commands.Command;
25 import org.apache.ibatis.migration.commands.Commands;
26 import org.apache.ibatis.migration.commands.InfoCommand;
27 import org.apache.ibatis.migration.commands.InitializeCommand;
28 import org.apache.ibatis.migration.options.Options;
29 import org.apache.ibatis.migration.options.SelectedOptions;
30 import org.apache.ibatis.migration.utils.Util;
31
32 public class CommandLine {
33
34 private final PrintStream console = System.out;
35 private final String[] args;
36
37 public CommandLine(String[] args) {
38 this.args = args;
39 }
40
41 public void execute() {
42 final SelectedOptions selectedOptions = parse(args);
43 if (selectedOptions.needsHelp()) {
44 printUsage();
45 return;
46 }
47 if (selectedOptions.getCommand() == null) {
48 console.printf("No command specified.%n");
49 printUsage();
50 return;
51 }
52 try {
53 Command command = Commands.resolveCommand(selectedOptions.getCommand(), selectedOptions);
54 if (command instanceof InitializeCommand || command instanceof InfoCommand
55 || validBasePath(selectedOptions.getPaths().getBasePath())) {
56 runCommand(command, selectedOptions);
57 }
58 } catch (Exception e) {
59 String errorMessage = e.getMessage();
60
61 if (hasColor(selectedOptions)) {
62 console.printf(ConsoleColors.RED + "%nERROR: %s%n", errorMessage + ConsoleColors.RESET);
63 } else {
64 console.printf("%nERROR: %s%n", errorMessage);
65 }
66
67 if (selectedOptions.isTrace()) {
68 e.printStackTrace();
69 }
70 console.close();
71 System.exit(1);
72 }
73 console.close();
74 }
75
76 private void runCommand(Command command, SelectedOptions selectedOptions) {
77 console.printf("------------------------------------------------------------------------%n");
78 console.printf("-- MyBatis Migrations - %s%n", selectedOptions.getCommand());
79 console.printf("------------------------------------------------------------------------%n");
80
81 long start = System.currentTimeMillis();
82 boolean exceptionCaught = false;
83
84 try {
85 command.execute(selectedOptions.getParams());
86 } catch (Throwable t) {
87 exceptionCaught = true;
88 if (t instanceof MigrationException) {
89 throw (MigrationException) t;
90 }
91 throw new MigrationException(t);
92 } finally {
93 console.printf("------------------------------------------------------------------------%n");
94
95 if (hasColor(selectedOptions)) {
96 console.printf("-- MyBatis Migrations %s%s%s%n", exceptionCaught ? ConsoleColors.RED : ConsoleColors.GREEN,
97 exceptionCaught ? "FAILURE" : "SUCCESS", ConsoleColors.RESET);
98 } else {
99 console.printf("-- MyBatis Migrations %s%n", exceptionCaught ? "FAILURE" : "SUCCESS");
100 }
101
102 console.printf("-- Total time: %ss%n", (System.currentTimeMillis() - start) / 1000);
103 console.printf("-- Finished at: %s%n", new Date());
104 printMemoryUsage();
105 console.printf("------------------------------------------------------------------------%n");
106 }
107 }
108
109 protected boolean hasColor(SelectedOptions selectedOptions) {
110 return selectedOptions.hasColor() || Util.getPropertyOptionAsBoolean(Options.COLOR.toString().toLowerCase());
111 }
112
113 private void printMemoryUsage() {
114 final Runtime runtime = Runtime.getRuntime();
115 final int megaUnit = 1024 * 1024;
116 final long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / megaUnit;
117 final long totalMemory = runtime.totalMemory() / megaUnit;
118
119 console.printf("-- Final Memory: %sM/%sM%n", usedMemory, totalMemory);
120 }
121
122 private boolean validBasePath(File basePath) {
123 final boolean validDirectory = basePath.exists() && basePath.isDirectory();
124
125 if (!validDirectory) {
126 console.printf("Migrations path must be a directory: %s%n", basePath.getAbsolutePath());
127 }
128
129 return validDirectory;
130 }
131
132 private void printUsage() {
133 console.printf(
134 "%nUsage: migrate command [parameter] [--path=<directory>] [--env=<environment>] [--template=<path to custom template>]%n%n");
135 console.printf("--path=<directory> Path to repository. Default current working directory.%n");
136 console.printf("--env=<environment> Environment to configure. Default environment is 'development'.%n");
137 console.printf("--template=<template> Path to custom template for creating new sql scripts.%n");
138 console.printf("--force Forces script to continue even if SQL errors are encountered.%n");
139 console.printf("--help Displays this usage message.%n");
140 console.printf("--trace Shows additional error details (if any).%n");
141 console.printf("--quiet Suppresses output.%n");
142 console.printf("--color Colorize output.%n");
143 console.printf("%n");
144 console.printf("Commands:%n");
145 console.printf(" info Display build version informations.%n");
146 console.printf(" init Creates (if necessary) and initializes a migration path.%n");
147 console.printf(" bootstrap Runs the bootstrap SQL script (see scripts/bootstrap.sql for more).%n");
148 console.printf(" new <description> Creates a new migration with the provided description.%n");
149 console.printf(" up [n] Run unapplied migrations, ALL by default, or 'n' specified.%n");
150 console
151 .printf(" down [n] Undoes migrations applied to the database. ONE by default or 'n' specified.%n");
152 console.printf(" version <version> Migrates the database up or down to the specified version.%n");
153 console.printf(" pending Force executes pending migrations out of order (not recommended).%n");
154 console.printf(" status Prints the changelog from the database if the changelog table exists.%n");
155 console
156 .printf(" script <v1> <v2> Generates a delta migration script from version v1 to v2 (undo if v1 > v2).%n");
157 console.printf("%n");
158 console.printf(" * Shortcuts are accepted by using the first few (unambiguous) letters of each command..%n");
159 console.printf("%n");
160 }
161 }