Revision f2808c21
Added by Andreas Kohlbecker over 3 years ago
src/main/java/eu/etaxonomy/drush/DrushExecuter.java | ||
---|---|---|
25 | 25 |
import org.apache.log4j.Level; |
26 | 26 |
import org.apache.log4j.Logger; |
27 | 27 |
|
28 |
import com.fasterxml.jackson.core.type.TypeReference; |
|
29 |
import com.fasterxml.jackson.databind.ObjectMapper; |
|
30 |
|
|
28 | 31 |
/** |
29 | 32 |
* Java executor for drush (https://www.drush.org/). |
30 | 33 |
* |
... | ... | |
55 | 58 |
} |
56 | 59 |
|
57 | 60 |
/** |
58 |
* List indexes returned from |
|
59 |
* <code>DrushExecuter.execute(DrushCommand cmd, String... value)</code>: |
|
61 |
* The execution of this command via |
|
62 |
* <code>DrushExecuter.execute({@linkplain DrushCommand#version})</code> results in |
|
63 |
* a {@code List<String>} return variable with the following elements: |
|
60 | 64 |
* |
61 | 65 |
* <ol> |
62 | 66 |
* <li>major</li> |
... | ... | |
72 | 76 |
public static DrushCommand coreStatus = new DrushCommand(Arrays.asList("core-status"), null, null); |
73 | 77 |
|
74 | 78 |
/** |
75 |
* List indexes returned from |
|
76 |
* <code>DrushExecuter.execute(DrushCommand cmd, String... value)</code>: |
|
77 |
* Multiple matches are possible: |
|
79 |
* Executes {@code drush vget --exact <variable-key>} |
|
80 |
* <p> |
|
81 |
* The execution of this command via |
|
82 |
* <code>DrushExecuter.execute({@linkplain DrushCommand#variableSet})</code> results in |
|
83 |
* a {@code List<String>} return variable with the following elements: |
|
84 |
* |
|
78 | 85 |
* <ol> |
79 | 86 |
* <li>value</li> |
80 | 87 |
* <li>value</li> |
81 | 88 |
* <li>value</li> |
82 | 89 |
* <ol> |
83 | 90 |
*/ |
84 |
public static DrushCommand variableGet = new DrushCommand(Arrays.asList("vget", "%s"), ".*:\\s+'(?<value>.*)'", |
|
85 |
null); |
|
86 |
|
|
91 |
public static DrushCommand variableGet = new DrushCommand(Arrays.asList("vget", "--exact", "--format=json", "%s")); |
|
87 | 92 |
/** |
88 |
* List indexes returned from |
|
89 |
* <code>DrushExecuter.execute(DrushCommand cmd, String... value)</code>: |
|
90 |
* Multiple matches are possible: |
|
93 |
* Executes {@code drush vset --exact <variable-key> <variable-value>} |
|
94 |
* <p> |
|
95 |
* The execution of this command via |
|
96 |
* <code>DrushExecuter.execute({@linkplain DrushCommand#variableSet})</code> results in |
|
97 |
* a {@code List<String>} return variable with the following elements: |
|
98 |
* |
|
91 | 99 |
* <ol> |
92 | 100 |
* <li>value</li> |
93 | 101 |
* <li>status</li> |
94 | 102 |
* <ol> |
95 | 103 |
*/ |
96 | 104 |
public static DrushCommand variableSet = new DrushCommand(Arrays.asList("--yes", "vset", "%s", "%s"), null, |
97 |
"[^\\\"]*\\\"(?<value>.*)\\\"\\.\\s+\\[(?<status>\\w+)\\]"); |
|
105 |
"[^\\\"]*\\\"(.*)\\\".*\\[(\\w+)\\]" |
|
106 |
); |
|
98 | 107 |
|
99 | 108 |
/** |
100 | 109 |
* @throws IOException |
... | ... | |
108 | 117 |
throw new RuntimeException("not yet implmented for Windows"); |
109 | 118 |
} |
110 | 119 |
|
111 |
List<String> matches = execute(version);
|
|
112 |
assert !matches.get(0).isEmpty() : "No suitable drush command found in the system";
|
|
113 |
String majorVersion = matches.get(0); |
|
120 |
List<Object> matches = execute(version);
|
|
121 |
assert !((String) matches.get(0)).isEmpty() : "No suitable drush command found in the system";
|
|
122 |
String majorVersion = (String) matches.get(0);
|
|
114 | 123 |
if (Integer.valueOf(majorVersion) < 8) { |
115 | 124 |
throw new RuntimeException("drush version >= 8 required"); |
116 | 125 |
} |
... | ... | |
123 | 132 |
* @throws InterruptedException |
124 | 133 |
* if the Process was interrupted |
125 | 134 |
*/ |
126 |
public List<String> execute(DrushCommand cmd, String... value) throws IOException, InterruptedException {
|
|
135 |
public List<Object> execute(DrushCommand cmd, String... value) throws IOException, InterruptedException {
|
|
127 | 136 |
|
128 | 137 |
List<String> executableWithArgs = new ArrayList<>(); |
129 | 138 |
|
... | ... | |
154 | 163 |
} |
155 | 164 |
} |
156 | 165 |
|
157 |
List<String> matches = new ArrayList<>();
|
|
166 |
List<Object> matches = new ArrayList<>();
|
|
158 | 167 |
|
159 | 168 |
ProcessBuilder pb = new ProcessBuilder(executableWithArgs); |
160 | 169 |
logger.debug("Command: " + pb.command().toString()); |
... | ... | |
162 | 171 |
int exitCode = process.waitFor(); |
163 | 172 |
|
164 | 173 |
if (exitCode == 0) { |
165 |
String out = readExecutionResponse(matches, process.getInputStream(), cmd.outRegex); |
|
166 |
String error = readExecutionResponse(matches, process.getErrorStream(), cmd.errRegex); |
|
174 |
String out, error; |
|
175 |
if(cmd.jsonResult) { |
|
176 |
out = readExecutionResponse(matches, process.getInputStream()); |
|
177 |
error = readExecutionResponse(matches, process.getErrorStream()); |
|
178 |
} else { |
|
179 |
out = readExecutionResponse(matches, process.getInputStream(), cmd.outRegex); |
|
180 |
error = readExecutionResponse(matches, process.getErrorStream(), cmd.errRegex); |
|
181 |
} |
|
167 | 182 |
if (out != null && !out.isEmpty()) { |
168 | 183 |
logger.error(error); |
169 | 184 |
} |
... | ... | |
176 | 191 |
return matches; |
177 | 192 |
} |
178 | 193 |
|
179 |
protected String readExecutionResponse(List<String> matches, InputStream stream, Pattern regex) throws IOException {
|
|
194 |
protected String readExecutionResponse(List<Object> matches, InputStream stream, Pattern regex) throws IOException {
|
|
180 | 195 |
String out; |
181 | 196 |
if (regex != null) { |
182 | 197 |
Scanner scanner = new Scanner(stream); |
... | ... | |
209 | 224 |
logger.debug(out); |
210 | 225 |
return out; |
211 | 226 |
} |
227 |
} |
|
212 | 228 |
|
229 |
/** |
|
230 |
* @param matches |
|
231 |
* @param stream |
|
232 |
* @return depending on the drupal variable type different return types are possible: |
|
233 |
* <ul> |
|
234 |
* <li>Object</li> |
|
235 |
* <li>List</li> |
|
236 |
* <li>List</li> |
|
237 |
* <li>String</li> |
|
238 |
* <li>Double</li> |
|
239 |
* <li>Integer</li> |
|
240 |
* </ul> |
|
241 |
* |
|
242 |
* @throws IOException |
|
243 |
*/ |
|
244 |
protected String readExecutionResponse(List<Object> matches, InputStream stream) throws IOException { |
|
245 |
String out = IOUtils.toString(stream); |
|
246 |
if(out != null) { |
|
247 |
out = out.trim(); |
|
248 |
if(!out.isEmpty()) { |
|
249 |
ObjectMapper mapper = new ObjectMapper(); |
|
250 |
if(out.startsWith("[")) { |
|
251 |
matches.add(mapper.readValue(out, new TypeReference<List<Object>>(){})); |
|
252 |
} else { |
|
253 |
matches.add(mapper.readValue(out, Object.class)); |
|
254 |
} |
|
255 |
if(matches.isEmpty()) { |
|
256 |
logger.debug("no result"); |
|
257 |
} else { |
|
258 |
logger.debug("result object: " + matches.get(0)); |
|
259 |
} |
|
260 |
} |
|
261 |
|
|
262 |
} |
|
263 |
return out; |
|
213 | 264 |
} |
214 | 265 |
|
215 | 266 |
public static class DrushCommand { |
216 | 267 |
|
217 | 268 |
Pattern outRegex; |
218 | 269 |
Pattern errRegex; |
270 |
boolean jsonResult = false; |
|
219 | 271 |
List<String> args = new ArrayList<>(); |
220 | 272 |
|
221 | 273 |
public DrushCommand(List<String> args, String outRegex, String errRegex) { |
... | ... | |
227 | 279 |
this.errRegex = Pattern.compile(errRegex, Pattern.MULTILINE); |
228 | 280 |
} |
229 | 281 |
} |
282 |
|
|
283 |
/** |
|
284 |
* For drush commands suopporting the {@code --format=json} option. |
|
285 |
* @param args |
|
286 |
*/ |
|
287 |
public DrushCommand(List<String> args) { |
|
288 |
this.args = args; |
|
289 |
this.jsonResult = true; |
|
290 |
} |
|
230 | 291 |
} |
231 | 292 |
|
232 | 293 |
/** |
... | ... | |
239 | 300 |
DrushExecuter.logger.setLevel(Level.DEBUG); |
240 | 301 |
try { |
241 | 302 |
DrushExecuter dex = new DrushExecuter(); |
303 |
List<Object> results; |
|
242 | 304 |
dex.setDrupalRoot(new File("/home/andreas/workspaces/www/drupal-7")); |
243 | 305 |
dex.setSiteURI(new URI("http://edit.test/d7/caryophyllales/")); |
244 |
dex.execute(coreStatus); |
|
245 |
dex.execute(help); |
|
246 |
List<String> results = dex.execute(variableSet, "cdm_webservice_url",
|
|
306 |
// dex.execute(coreStatus);
|
|
307 |
// dex.execute(help);
|
|
308 |
results = dex.execute(variableSet, "cdm_webservice_url", |
|
247 | 309 |
"http://api.cybertaxonomy.org/cyprus/"); |
248 | 310 |
if (!results.get(0).equals("http://api.cybertaxonomy.org/cyprus/")) { |
249 | 311 |
throw new RuntimeException("unexpected result item 0: " + results.get(0)); |
... | ... | |
251 | 313 |
if (!results.get(1).equals("success")) { |
252 | 314 |
throw new RuntimeException("unexpected result item 1: " + results.get(0)); |
253 | 315 |
} |
316 |
results = dex.execute(variableGet, "cdm_webservice_url"); |
|
317 |
if (!results.get(0).equals("http://api.cybertaxonomy.org/cyprus/")) { |
|
318 |
throw new RuntimeException("unexpected result item 0: " + results.get(0)); |
|
319 |
} |
|
254 | 320 |
// testing remote execution via ssh |
255 | 321 |
dex.sshHost = "edit-int"; |
256 | 322 |
dex.setDrupalRoot(new File("/var/www/drupal-7")); |
Also available in: Unified diff
ref #9181 DrushExecuter reading json values