View Javadoc

1   package liquibase.change.core;
2   
3   import liquibase.change.AbstractChange;
4   import liquibase.change.ChangeMetaData;
5   import liquibase.database.Database;
6   import liquibase.exception.UnexpectedLiquibaseException;
7   import liquibase.exception.ValidationErrors;
8   import liquibase.exception.Warnings;
9   import liquibase.executor.Executor;
10  import liquibase.executor.ExecutorService;
11  import liquibase.executor.LoggingExecutor;
12  import liquibase.logging.LogFactory;
13  import liquibase.sql.Sql;
14  import liquibase.statement.SqlStatement;
15  import liquibase.statement.core.CommentStatement;
16  import liquibase.statement.core.RuntimeStatement;
17  import liquibase.util.StreamUtil;
18  import liquibase.util.StringUtils;
19  
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  /**
26   * Executes a given shell executable.
27   */
28  public class ExecuteShellCommandChange extends AbstractChange {
29  
30      private String executable;
31      private List<String> os;
32      private List<String> args = new ArrayList<String>();
33  
34      public ExecuteShellCommandChange() {
35          super("executeCommand", "Execute Shell Command", ChangeMetaData.PRIORITY_DEFAULT);
36      }
37  
38      public String getExecutable() {
39          return executable;
40      }
41  
42      public void setExecutable(String executable) {
43          this.executable = executable;
44      }
45  
46      public void addArg(String arg) {
47          this.args.add(arg);
48      }
49  
50      public void setOs(String os) {
51          this.os = StringUtils.splitAndTrim(os, ",");
52      }
53  
54      public List<String> getOs() {
55          return os;
56      }
57  
58      @Override
59      public ValidationErrors validate(Database database) {
60          return new ValidationErrors();
61      }
62  
63      @Override
64      public Warnings warn(Database database) {
65          return new Warnings();
66      }
67  
68      public SqlStatement[] generateStatements(final Database database) {
69          boolean shouldRun = true;
70          if (os != null && os.size() > 0) {
71              String currentOS = System.getProperty("os.name");
72              if (!os.contains(currentOS)) {
73                  shouldRun = false;
74                  LogFactory.getLogger().info("Not executing on os " + currentOS + " when " + os + " was specified");
75              }
76          }
77  
78          // check if running under not-executed mode (logging output)
79          boolean nonExecutedMode = false;
80          Executor executor = ExecutorService.getInstance().getExecutor(database);
81          if (executor instanceof LoggingExecutor) {
82              nonExecutedMode = true;
83          }
84  
85          if (shouldRun && !nonExecutedMode) {
86  
87              return new SqlStatement[] { new RuntimeStatement() {
88  
89                  @Override
90                  public Sql[] generate(Database database) {
91                      List<String> commandArray = new ArrayList<String>();
92                      commandArray.add(executable);
93                      commandArray.addAll(args);
94  
95                      try {
96                          ProcessBuilder pb = new ProcessBuilder(commandArray);
97                          pb.redirectErrorStream(true);
98                          Process p = pb.start();
99                          int returnCode = 0;
100                         try {
101                             returnCode = p.waitFor();
102                         } catch (InterruptedException e) {
103                             ;
104                         }
105 
106                         ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
107                         ByteArrayOutputStream inputStream = new ByteArrayOutputStream();
108                         StreamUtil.copy(p.getErrorStream(), errorStream);
109                         StreamUtil.copy(p.getInputStream(), inputStream);
110 
111                         LogFactory.getLogger().severe(errorStream.toString());
112                         LogFactory.getLogger().info(inputStream.toString());
113 
114                         if (returnCode != 0) {
115                             throw new RuntimeException(getCommandString() + " returned an code of " + returnCode);
116                         }
117                     } catch (IOException e) {
118                         throw new UnexpectedLiquibaseException("Error executing command: " + e);
119                     }
120 
121                     return null;
122                 }
123             } };
124         }
125 
126         if (nonExecutedMode) {
127             return new SqlStatement[] { new CommentStatement(getCommandString()) };
128         }
129 
130         return new SqlStatement[0];
131     }
132 
133     public String getConfirmationMessage() {
134         return "Shell command '" + getCommandString() + "' executed";
135     }
136 
137     private String getCommandString() {
138         return executable + " " + StringUtils.join(args, " ");
139     }
140 }